[Fleet] Fix privileges for enrollment and access api keys (#60534) (#60560)

This commit is contained in:
Nicolas Chaulet 2020-03-18 18:14:08 -04:00 committed by GitHub
parent fb91b91a13
commit 9a6f510cc6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 148 additions and 7 deletions

View file

@ -93,7 +93,19 @@ export async function generateEnrollmentAPIKey(
const name = providedKeyName ? `${providedKeyName} (${id})` : id;
const key = await createAPIKey(soClient, name, {});
const key = await createAPIKey(soClient, name, {
// Useless role to avoid to have the privilege of the user that created the key
'fleet-apikey-enroll': {
cluster: [],
applications: [
{
application: '.fleet',
privileges: ['no-privileges'],
resources: ['*'],
},
],
},
});
if (!key) {
throw new Error('Unable to create an enrollment api key');

View file

@ -42,7 +42,17 @@ export async function generateAccessApiKey(
configId: string
) {
const key = await createAPIKey(soClient, agentId, {
'fleet-agent': {},
// Useless role to avoid to have the privilege of the user that created the key
'fleet-apikey-access': {
cluster: [],
applications: [
{
application: '.fleet',
privileges: ['no-privileges'],
resources: ['*'],
},
],
},
});
if (!key) {

View file

@ -6,8 +6,9 @@
import expect from '@kbn/expect';
import uuid from 'uuid';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { getSupertestWithoutAuth, setupIngest } from './services';
import { getSupertestWithoutAuth, setupIngest, getEsClientForAPIKey } from './services';
export default function(providerContext: FtrProviderContext) {
const { getService } = providerContext;
@ -104,5 +105,61 @@ export default function(providerContext: FtrProviderContext) {
expect(apiResponse.success).to.eql(true);
expect(apiResponse.item).to.have.keys('id', 'active', 'access_api_key', 'type', 'config_id');
});
it('when enrolling an agent it should generate an access api key with limited privileges', async () => {
const { body: apiResponse } = await supertest
.post(`/api/ingest_manager/fleet/agents/enroll`)
.set('kbn-xsrf', 'xxx')
.set(
'Authorization',
`ApiKey ${Buffer.from(`${apiKey.id}:${apiKey.api_key}`).toString('base64')}`
)
.send({
type: 'PERMANENT',
metadata: {
local: {},
user_provided: {},
},
})
.expect(200);
expect(apiResponse.success).to.eql(true);
const { body: privileges } = await getEsClientForAPIKey(
providerContext,
apiResponse.item.access_api_key
).security.hasPrivileges({
body: {
cluster: ['all', 'monitor', 'manage_api_key'],
index: [
{
names: ['log-*', 'metrics-*', 'events-*', '*'],
privileges: ['write', 'create_index'],
},
],
},
});
expect(privileges.cluster).to.eql({
all: false,
monitor: false,
manage_api_key: false,
});
expect(privileges.index).to.eql({
'*': {
create_index: false,
write: false,
},
'events-*': {
create_index: false,
write: false,
},
'log-*': {
create_index: false,
write: false,
},
'metrics-*': {
create_index: false,
write: false,
},
});
});
});
}

View file

@ -5,7 +5,8 @@
*/
import supertestAsPromised from 'supertest-as-promised';
import url from 'url';
import { Client } from '@elastic/elasticsearch';
import { format as formatUrl } from 'url';
import { FtrProviderContext } from '../../../ftr_provider_context';
@ -15,7 +16,19 @@ export function getSupertestWithoutAuth({ getService }: FtrProviderContext) {
kibanaUrl.auth = null;
kibanaUrl.password = null;
return supertestAsPromised(url.format(kibanaUrl));
return supertestAsPromised(formatUrl(kibanaUrl));
}
export function getEsClientForAPIKey({ getService }: FtrProviderContext, esApiKey: string) {
const config = getService('config');
const url = formatUrl({ ...config.get('servers.elasticsearch'), auth: false });
return new Client({
nodes: [url],
auth: {
apiKey: esApiKey,
},
requestTimeout: config.get('timeouts.esRequestTimeout'),
});
}
export function setupIngest({ getService }: FtrProviderContext) {

View file

@ -7,11 +7,12 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { setupIngest } from '../agents/services';
import { setupIngest, getEsClientForAPIKey } from '../agents/services';
const ENROLLMENT_KEY_ID = 'ed22ca17-e178-4cfe-8b02-54ea29fbd6d0';
export default function({ getService }: FtrProviderContext) {
export default function(providerContext: FtrProviderContext) {
const { getService } = providerContext;
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
@ -78,6 +79,54 @@ export default function({ getService }: FtrProviderContext) {
expect(apiResponse.success).to.eql(true);
expect(apiResponse.item).to.have.keys('id', 'api_key', 'api_key_id', 'name', 'config_id');
});
it('should create an ES ApiKey with limited privileges', async () => {
const { body: apiResponse } = await supertest
.post(`/api/ingest_manager/fleet/enrollment-api-keys`)
.set('kbn-xsrf', 'xxx')
.send({
config_id: 'policy1',
})
.expect(200);
expect(apiResponse.success).to.eql(true);
const { body: privileges } = await getEsClientForAPIKey(
providerContext,
apiResponse.item.api_key
).security.hasPrivileges({
body: {
cluster: ['all', 'monitor', 'manage_api_key'],
index: [
{
names: ['log-*', 'metrics-*', 'events-*', '*'],
privileges: ['write', 'create_index'],
},
],
},
});
expect(privileges.cluster).to.eql({
all: false,
monitor: false,
manage_api_key: false,
});
expect(privileges.index).to.eql({
'*': {
create_index: false,
write: false,
},
'events-*': {
create_index: false,
write: false,
},
'log-*': {
create_index: false,
write: false,
},
'metrics-*': {
create_index: false,
write: false,
},
});
});
});
});
}