Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

policyfiles actions added #6081

Merged
merged 1 commit into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 103 additions & 100 deletions api/external/infra_proxy/infra_proxy.pb.go

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions api/external/infra_proxy/infra_proxy.pb.policy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions api/external/infra_proxy/infra_proxy.proto
Original file line number Diff line number Diff line change
Expand Up @@ -310,25 +310,25 @@ service InfraProxy {
rpc GetPolicyfiles (infra_proxy.request.Policyfiles) returns (infra_proxy.response.Policyfiles) {
option (google.api.http).get = "/api/v0/infra/servers/{server_id}/orgs/{org_id}/policyfiles";
option (chef.automate.api.iam.policy).resource = "infra:infraServers:{server_id}:orgs:{org_id}:policyfiles";
option (chef.automate.api.iam.policy).action = "infra:infraServers:get";
option (chef.automate.api.iam.policy).action = "infra:infraServersOrgsPolicyFiles:get";
};

rpc GetPolicyfile (infra_proxy.request.Policyfile) returns (infra_proxy.response.Policyfile) {
option (google.api.http).get = "/api/v0/infra/servers/{server_id}/orgs/{org_id}/policyfiles/{name}";
option (chef.automate.api.iam.policy).resource = "infra:infraServers:{server_id}:orgs:{org_id}:policyfiles";
option (chef.automate.api.iam.policy).action = "infra:infraServers:get";
option (chef.automate.api.iam.policy).action = "infra:infraServersOrgsPolicyFiles:get";
};

rpc DeletePolicyfile (infra_proxy.request.DeletePolicyfile) returns (infra_proxy.response.DeletePolicyfile) {
option (google.api.http).delete = "/api/v0/infra/servers/{server_id}/orgs/{org_id}/policyfiles/{name}";
option (chef.automate.api.iam.policy).resource = "infra:infraServers:{server_id}:orgs:{org_id}:policyfiles";
option (chef.automate.api.iam.policy).action = "infra:infraServers:update";
option (chef.automate.api.iam.policy).action = "infra:infraServersOrgsPolicyFiles:delete";
};

rpc GetPolicyfileRevisions (infra_proxy.request.PolicyfileRevisions) returns (infra_proxy.response.PolicyfileRevisions) {
option (google.api.http).get = "/api/v0/infra/servers/{server_id}/orgs/{org_id}/policyfiles/{name}/revisions";
option (chef.automate.api.iam.policy).resource = "infra:infraServers:{server_id}:orgs:{org_id}:policyfiles";
option (chef.automate.api.iam.policy).action = "infra:infraServers:get";
option (chef.automate.api.iam.policy).action = "infra:infraServersOrgsPolicyFiles:get";
};

rpc GetPolicygroup (infra_proxy.request.Policygroup) returns (infra_proxy.response.Policygroup) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
</div>
<chef-loading-spinner class="full-screen-spinner" *ngIf="deleting" size="50" fixed></chef-loading-spinner>
<div id="policy-file-table-container" *ngIf="policyFiles.length" data-cy="policy-file-table-container">
<app-authorized [allOf]="['/api/v0/infra/servers/{server_id}/orgs/{org_id}/policyfiles', 'get', [serverId, orgId]]">
<chef-table>
<chef-thead *ngIf="!searchFlag || searchArr.length">
<chef-tr class="no_border_tr">
Expand All @@ -47,18 +48,21 @@
Revisions
<chef-icon aria-hidden="true" class="primary">add</chef-icon>
</mat-option>
<mat-option
data-cy="delete"
class="secondary"
(onSelectionChange)="startpolicyFilesDelete(policyFile)">
Delete
<chef-icon aria-hidden="true" class="primary">remove</chef-icon>
</mat-option>
<app-authorized [allOf]="['/api/v0/infra/servers/{server_id}/orgs/{org_id}/policyfiles/{name}', 'delete', [serverId, orgId, policyFile.name]]">
<mat-option
data-cy="delete"
class="secondary"
(onSelectionChange)="startpolicyFilesDelete(policyFile)">
Delete
<chef-icon aria-hidden="true" class="primary">remove</chef-icon>
</mat-option>
</app-authorized>
</mat-select>
</chef-td>
</chef-tr>
</chef-tbody>
</chef-table>
</app-authorized>
</div>
<app-pagination *ngIf="!searchFlag"
[items]="policyFiles"
Expand Down
4 changes: 3 additions & 1 deletion dev-docs/infra-server-iam.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,6 @@ example_fqdn "automate" >}}/api/v0/infra/servers/{id} |
| Create DataBagItem | POST | infra:infraServersOrgsDataBagsItem:create | /api/v0/infra/servers/{server_id}/orgs/{org_id}/data_bags/{name} | https://{{< example_fqdn "automate" >}}/api/v0/infra/servers/{server_id}/orgs/{org_id}/data_bags/{name} |
| Update DataBagItem | PUT | infra:infraServersOrgsDataBagsItem:update | /api/v0/infra/servers/{server_id}/orgs/{org_id}/data_bags/{name}/{item_id} | https://{{< example_fqdn "automate" >}}/api/v0/infra/servers/{server_id}/orgs/{org_id}/data_bags/{name}/{item_id} |
| Delete DataBagsItem | DELETE | infra:infraServersOrgsDataBagsItem:delete | /api/v0/infra/servers/{server_id}/orgs/{org_id}/data_bags/{name}/{item} | https://{{< example_fqdn "automate" >}}/api/v0/infra/servers/{server_id}/orgs/{org_id}/data_bags/{name}/{item} |
| Delete DataBags | DELETE | infra:infraServersOrgsDataBags:delete | /api/v0/infra/servers/{server_id}/orgs/{org_id}/data_bags/{name} | https://{{< example_fqdn "automate" >}}/api/v0/infra/servers/{server_id}/orgs/{org_id}/data_bags/{name} |
| Delete DataBags | DELETE | infra:infraServersOrgsDataBags:delete | /api/v0/infra/servers/{server_id}/orgs/{org_id}/data_bags/{name} | https://{{< example_fqdn "automate" >}}/api/v0/infra/servers/{server_id}/orgs/{org_id}/data_bags/{name} |
| Get PolicyFiles | GET | infra:infraServersOrgsPolicyFiles:get | /api/v0/infra/servers/{server_id}/orgs/{org_id}/policyfiles| https://{{< example_fqdn "automate" >}}/api/v0/infra/servers/{server_id}/orgs/{org_id}/policyfiles |
| Delete PolicyFiles | DELETE | infra:infraServersOrgsPolicyFiles:delete | /api/v0/infra/servers/{server_id}/orgs/{org_id}/policyfiles/{name}| https://{{< example_fqdn "automate" >}}/api/v0/infra/servers/{server_id}/orgs/{org_id}/policyfiles/{name} |
227 changes: 227 additions & 0 deletions e2e/cypress/integration/api/iam/policyfiles_actions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
describe('PolicyFiles get', () => {
let withInfraServersPolicyFlesGetActionToken = '';
let withoutInfraServersPolicyFlesGetActionToken = '';

const cypressPrefix = 'infra-server-policyfiles-actions-get';
const policyId1 = `${cypressPrefix}-pol-1-${Cypress.moment().format('MMDDYYhhmm')}`;
const policyId2 = `${cypressPrefix}-pol-2-${Cypress.moment().format('MMDDYYhhmm')}`;
const tokenId1 = `${cypressPrefix}-token-1-${Cypress.moment().format('MMDDYYhhmm')}`;
const tokenId2 = `${cypressPrefix}-token-2-${Cypress.moment().format('MMDDYYhhmm')}`;
const objectsToCleanUp = ['tokens', 'policies'];

const withInfraServersPolicyFilesPolicy = {
id: policyId1,
name: tokenId1,
projects: [],
members: [`token:${tokenId1}`],
statements: [
{
effect: 'ALLOW',
actions: [
'infra:infraServersOrgsPolicyFiles:get'
],
projects: ['*']
}]
};


const withoutInfraServersPolicyFilesPolicy = {
id: policyId2,
name: tokenId2,
projects: [],
members: [`token:${tokenId2}`],
statements: [
{
effect: 'DENY',
actions: [
'infra:infraServersOrgsPolicyFiles:get'
],
projects: ['*']
}]
};

before(() => {
cy.cleanupIAMObjectsByIDPrefixes(cypressPrefix, objectsToCleanUp);

cy.request({
headers: { 'api-token': Cypress.env('ADMIN_TOKEN') },
method: 'POST',
url: '/apis/iam/v2/tokens',
body: {
id: tokenId1,
name: tokenId1
}
}).then((resp) => {
withInfraServersPolicyFlesGetActionToken = resp.body.token.value;
});

cy.request({
headers: { 'api-token': Cypress.env('ADMIN_TOKEN') },
method: 'POST',
url: '/apis/iam/v2/policies',
body: withInfraServersPolicyFilesPolicy
}).then((resp) => {
expect(resp.status).to.equal(200);
});

cy.request({
headers: { 'api-token': Cypress.env('ADMIN_TOKEN') },
method: 'POST',
url: '/apis/iam/v2/tokens',
body: {
id: tokenId2,
name: tokenId2
}
}).then((resp) => {
withoutInfraServersPolicyFlesGetActionToken = resp.body.token.value;
});

cy.request({
headers: { 'api-token': Cypress.env('ADMIN_TOKEN') },
method: 'POST',
url: '/apis/iam/v2/policies',
body: withoutInfraServersPolicyFilesPolicy
}).then((resp) => {
expect(resp.status).to.equal(200);
});
});

after(() => {
cy.cleanupIAMObjectsByIDPrefixes(cypressPrefix, objectsToCleanUp);
});

it('policyfiles get returns 200 when get actions is allowed', () => {
cy.request({
headers: { 'api-token': withInfraServersPolicyFlesGetActionToken },
method: 'GET',
url: '/api/v0/infra/servers/local-dev/orgs/test-org/policyfiles'
}).then((resp) => {
assert.equal(resp.status, 200);
});
});

it('policyfiles get returns 403 when get actions is denied', () => {
cy.request({
headers: { 'api-token': withoutInfraServersPolicyFlesGetActionToken },
method: 'GET',
url: '/api/v0/infra/servers/local-dev/orgs/test-org/policyfiles',
failOnStatusCode: false
}).then((resp) => {
assert.equal(resp.status, 403);
});
});
});

describe('PolicyFiles delete', () => {
let withInfraServersPolicyFilesDeleteActionToken = '';
let withoutInfraServersPolicyFilesDeleteActionToken = '';

const cypressPrefix = 'infra-server-policyfiles-actions-delete';
const policyId1 = `${cypressPrefix}-pol-1-${Cypress.moment().format('MMDDYYhhmm')}`;
const policyId2 = `${cypressPrefix}-pol-2-${Cypress.moment().format('MMDDYYhhmm')}`;
const tokenId1 = `${cypressPrefix}-token-1-${Cypress.moment().format('MMDDYYhhmm')}`;
const tokenId2 = `${cypressPrefix}-token-2-${Cypress.moment().format('MMDDYYhhmm')}`;
const objectsToCleanUp = ['tokens', 'policies'];

const withInfraServersPolicyFilesDeletePolicy = {
id: policyId1,
name: tokenId1,
projects: [],
members: [`token:${tokenId1}`],
statements: [
{
effect: 'ALLOW',
actions: [
'infra:infraServersOrgsPolicyFiles:delete'
],
projects: ['*']
}]
};


const withoutInfraServersPolicyFilesDeletePolicy = {
id: policyId2,
name: tokenId2,
projects: [],
members: [`token:${tokenId2}`],
statements: [
{
effect: 'DENY',
actions: [
'infra:infraServersOrgsPolicyFiles:delete'
],
projects: ['*']
}]
};

before(() => {
cy.cleanupIAMObjectsByIDPrefixes(cypressPrefix, objectsToCleanUp);

cy.request({
headers: { 'api-token': Cypress.env('ADMIN_TOKEN') },
method: 'POST',
url: '/apis/iam/v2/tokens',
body: {
id: tokenId1,
name: tokenId1
}
}).then((resp) => {
withInfraServersPolicyFilesDeleteActionToken = resp.body.token.value;
});

cy.request({
headers: { 'api-token': Cypress.env('ADMIN_TOKEN') },
method: 'POST',
url: '/apis/iam/v2/policies',
body: withInfraServersPolicyFilesDeletePolicy
}).then((resp) => {
expect(resp.status).to.equal(200);
});

cy.request({
headers: { 'api-token': Cypress.env('ADMIN_TOKEN') },
method: 'POST',
url: '/apis/iam/v2/tokens',
body: {
id: tokenId2,
name: tokenId2
}
}).then((resp) => {
withoutInfraServersPolicyFilesDeleteActionToken = resp.body.token.value;
});

cy.request({
headers: { 'api-token': Cypress.env('ADMIN_TOKEN') },
method: 'POST',
url: '/apis/iam/v2/policies',
body: withoutInfraServersPolicyFilesDeletePolicy
}).then((resp) => {
expect(resp.status).to.equal(200);
});
});

after(() => {
cy.cleanupIAMObjectsByIDPrefixes(cypressPrefix, objectsToCleanUp);
});

it('policyfiles delete returns 403 when delete actions is denied', () => {
cy.request({
headers: { 'api-token': withoutInfraServersPolicyFilesDeleteActionToken },
method: 'DELETE',
url: '/api/v0/infra/servers/local-dev/orgs/test-org/policyfiles/examplecb',
failOnStatusCode: false
}).then((resp) => {
assert.equal(resp.status, 403);
});
});

it('policyfiles delete returns 200 when delete actions is allowed', () => {
cy.request({
headers: { 'api-token': withInfraServersPolicyFilesDeleteActionToken },
method: 'DELETE',
url: '/api/v0/infra/servers/local-dev/orgs/test-org/policyfiles/examplecb'
}).then((resp) => {
assert.equal(resp.status, 200);
});
});
});