Skip to content

Commit

Permalink
Set creator principal id annotation when creating projects and v3 clu…
Browse files Browse the repository at this point in the history
…sters (#12233)

* set principal id annotation when creating projects

* set creator principal id when creating kontainer and machine driver clusters

* correct kontainer provisioning principal id annotation

* add test for project creation

* fix projects afterEach hook
  • Loading branch information
mantis-toboggan-md authored Oct 15, 2024
1 parent 4e0aa07 commit 0f723dd
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 8 deletions.
42 changes: 42 additions & 0 deletions cypress/e2e/blueprints/explorer/rbac/third-party-principals-get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const res = {
type: 'collection',
links: { self: 'https://localhost:8005/v3/principals' },
actions: { search: 'https://localhost:8005/v3/principals?action=search' },
pagination: { limit: 1000 },
sort: {
order: 'asc',
reverse: 'https://localhost:8005/v3/principals?order=desc',
links: {
loginName: 'https://localhost:8005/v3/principals?sort=loginName', name: 'https://localhost:8005/v3/principals?sort=name', principalType: 'https://localhost:8005/v3/principals?sort=principalType', profilePicture: 'https://localhost:8005/v3/principals?sort=profilePicture', profileURL: 'https://localhost:8005/v3/principals?sort=profileURL', provider: 'https://localhost:8005/v3/principals?sort=provider', uuid: 'https://localhost:8005/v3/principals?sort=uuid'
}
},
filters: {
created: null, creatorId: null, id: null, loginName: null, me: null, memberOf: null, name: null, principalType: null, profilePicture: null, profileURL: null, provider: null, removed: null, uuid: null
},
resourceType: 'principal',
data: [
{
baseType: 'principal',
created: null,
creatorId: null,
id: 'github://1234567890',
links: { self: 'https://localhost:8005/v3/principals/github:%2F%2F1234567890' },
loginName: 'admin',
me: true,
memberOf: false,
name: 'Default Admin',
principalType: 'user',
provider: 'github',
type: 'principal'
}
]
};

export function spoofThirdPartyPrincipal(): Cypress.Chainable<Response> {
return cy.intercept('GET', '/v3/principals', (req) => {
req.reply({
statusCode: 200,
body: res
});
}).as('spoofThirdPartyPrincipal');
}
52 changes: 45 additions & 7 deletions cypress/e2e/tests/pages/explorer2/project-namespace.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ProjectsNamespacesPagePo from '@/cypress/e2e/po/pages/explorer/projects-namespaces.po';
import { spoofThirdPartyPrincipal } from '@/cypress/e2e/blueprints/explorer/rbac/third-party-principals-get';

describe('Projects/Namespaces', { tags: ['@explorer2', '@adminUser'] }, () => {
const projectsNamespacesPage = new ProjectsNamespacesPagePo('local');
Expand All @@ -19,23 +20,60 @@ describe('Projects/Namespaces', { tags: ['@explorer2', '@adminUser'] }, () => {
projectsNamespacesPage.nsProject().checkExists();
});

describe('Create Project validation', () => {
describe('Project creation', () => {
beforeEach(() => {
cy.createE2EResourceName('proj').as('projectName');
cy.intercept('POST', '/v3/projects').as('createProjectRequest');
});

it('sets the creator principal id annotation when creating a project and using third-party auth', () => {
cy.get('@projectName').then((projectName) => {
// intercept the request to /v3/principals and return a principal authenticated by github instead of local
spoofThirdPartyPrincipal();

projectsNamespacesPage.createProjectButtonClick();
projectsNamespacesPage.name().set(projectName);
projectsNamespacesPage.buttonSubmit().click();

cy.wait('@createProjectRequest').then(({ request, response }) => {
expect(request.body.annotations['field.cattle.io/creator-principal-name']).to.equal('github://1234567890');
expect(response.body.annotations['field.cattle.io/creator-principal-name']).to.equal('github://1234567890');
});
});
});

it('does not set a creator principal id annotation when creating a project if using local auth', () => {
cy.get('@projectName').then((projectName) => {
projectsNamespacesPage.createProjectButtonClick();
projectsNamespacesPage.name().set(projectName);
projectsNamespacesPage.buttonSubmit().click();

cy.wait('@createProjectRequest').then(({ request, response }) => {
expect(request.body.annotations).to.not.have.property('field.cattle.io/creator-principal-name');
expect(response.body.annotations).to.not.have.property('field.cattle.io/creator-principal-name');
});
});
});

afterEach(() => {
cy.get('@projectName').then((projectName) => {
cy.deleteRancherResource('v3', 'projects', projectName, false);
});
});
});

describe('Project Error Banner and Validation', () => {
beforeEach(() => {
projectsNamespacesPage.goTo();
});

// Issue 5975: create button should be disabled unless name is filled in
it('Create button becomes available if the name is filled in', () => {
projectsNamespacesPage.createProjectButtonClick();
projectsNamespacesPage.buttonSubmit().expectToBeDisabled();
projectsNamespacesPage.name().set('test-1234');
projectsNamespacesPage.buttonSubmit().expectToBeEnabled();
});
});

describe('Create Project Error Banner', () => {
beforeEach(() => {
projectsNamespacesPage.goTo();
});

it('displays an error message when submitting a form with errors', () => {
projectsNamespacesPage.createProjectButtonClick();
Expand Down
6 changes: 6 additions & 0 deletions pkg/aks/components/CruAks.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import {
nodePoolNamesUnique,
nodePoolCount
} from '../util/validators';
import { CREATOR_PRINCIPAL_ID } from '@shell/config/labels-annotations';
export const defaultNodePool = {
availabilityZones: ['1', '2', '3'],
Expand Down Expand Up @@ -95,6 +96,7 @@ const defaultCluster = {
enableClusterMonitoring: false,
enableNetworkPolicy: false,
labels: {},
annotations: {},
windowsPreferedCluster: false,
};
Expand Down Expand Up @@ -161,6 +163,10 @@ export default defineComponent({
this.originalVersion = this.normanCluster?.aksConfig?.kubernetesVersion;
} else {
this.normanCluster = await store.dispatch('rancher/create', { type: NORMAN.CLUSTER, ...defaultCluster }, { root: true });
if (!this.$store.getters['auth/principalId'].includes('local://')) {
this.normanCluster.annotations[CREATOR_PRINCIPAL_ID] = this.$store.getters['auth/principalId'];
}
}
if (!this.normanCluster.aksConfig) {
this.normanCluster['aksConfig'] = { ...defaultAksConfig };
Expand Down
5 changes: 5 additions & 0 deletions pkg/eks/components/CruEKS.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ import Config from './Config.vue';
import Networking from './Networking.vue';
import AccountAccess from './AccountAccess.vue';
import EKSValidators from '../util/validators';
import { CREATOR_PRINCIPAL_ID } from '@shell/config/labels-annotations';
const DEFAULT_CLUSTER = {
dockerRootDir: '/var/lib/docker',
enableClusterAlerting: false,
enableClusterMonitoring: false,
enableNetworkPolicy: false,
labels: {},
annotations: {},
windowsPreferedCluster: false,
fleetAgentDeploymentCustomization: {},
clusterAgentDeploymentCustomization: {}
Expand Down Expand Up @@ -127,6 +129,9 @@ export default defineComponent({
this.originalVersion = this.normanCluster?.eksConfig?.kubernetesVersion || '';
} else {
this.normanCluster = await store.dispatch('rancher/create', { type: NORMAN.CLUSTER, ...DEFAULT_CLUSTER }, { root: true });
if (!this.$store.getters['auth/principalId'].includes('local://')) {
this.normanCluster.annotations[CREATOR_PRINCIPAL_ID] = this.$store.getters['auth/principalId'];
}
}
if (!this.normanCluster.eksConfig) {
Expand Down
5 changes: 5 additions & 0 deletions pkg/gke/components/CruGKE.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
clusterNameChars, clusterNameStartEnd, requiredInCluster, ipv4WithCidr, ipv4oripv6WithCidr, GKEInitialCount
} from '../util/validators';
import { diffUpstreamSpec, syncUpstreamConfig } from '@shell/utils/kontainer';
import { CREATOR_PRINCIPAL_ID } from '@shell/config/labels-annotations';
const defaultMachineType = 'n1-standard-2';
Expand Down Expand Up @@ -124,6 +125,7 @@ const defaultCluster = {
enableClusterMonitoring: false,
enableNetworkPolicy: false,
labels: {},
annotations: {},
windowsPreferedCluster: false,
};
Expand Down Expand Up @@ -174,6 +176,9 @@ export default defineComponent({
this.originalVersion = this.normanCluster?.gkeConfig?.kubernetesVersion;
} else {
this.normanCluster = await store.dispatch('rancher/create', { type: NORMAN.CLUSTER, ...defaultCluster }, { root: true });
if (!this.$store.getters['auth/principalId'].includes('local://')) {
this.normanCluster.annotations[CREATOR_PRINCIPAL_ID] = this.$store.getters['auth/principalId'];
}
}
// ensure any fields editable through this UI that have been altered in aws are shown here - see syncUpstreamConfig jsdoc for details
if (!this.isNewOrUnprovisioned) {
Expand Down
1 change: 1 addition & 0 deletions shell/config/labels-annotations.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const CATTLE_PUBLIC_ENDPOINTS = 'field.cattle.io/publicEndpoints';
export const TARGET_WORKLOADS = 'field.cattle.io/targetWorkloadIds';
export const UI_MANAGED = 'management.cattle.io/ui-managed';
export const CREATOR_ID = 'field.cattle.io/creatorId';
export const CREATOR_PRINCIPAL_ID = 'field.cattle.io/creator-principal-name';
export const RESOURCE_QUOTA = 'field.cattle.io/resourceQuota';
export const AZURE_MIGRATED = 'auth.cattle.io/azuread-endpoint-migrated';
export const WORKSPACE_ANNOTATION = 'objectset.rio.cattle.io/id';
Expand Down
5 changes: 4 additions & 1 deletion shell/edit/management.cattle.io.project.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { MANAGEMENT } from '@shell/config/types';
import { NAME } from '@shell/config/product/explorer';
import { PROJECT_ID, _VIEW, _CREATE, _EDIT } from '@shell/config/query-params';
import ProjectMembershipEditor, { canViewProjectMembershipEditor } from '@shell/components/form/Members/ProjectMembershipEditor';
import { CREATOR_PRINCIPAL_ID } from '@shell/config/labels-annotations';
import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
import { Banner } from '@components/Banner';
Expand Down Expand Up @@ -103,6 +103,9 @@ export default {
this.value.metadata['namespace'] = this.$store.getters['currentCluster'].id;
this.value['spec'] = this.value.spec || {};
this.value.spec['containerDefaultResourceLimit'] = this.value.spec.containerDefaultResourceLimit || {};
if (!this.$store.getters['auth/principalId'].includes('local://')) {
this.value.metadata.annotations[CREATOR_PRINCIPAL_ID] = this.$store.getters['auth/principalId'];
}
},
methods: {
async save(saveCb) {
Expand Down

0 comments on commit 0f723dd

Please sign in to comment.