use existing annotations as metadata keys
Signed-off-by: Jamie Klassen <jklassen@vmware.com>
This commit is contained in:
@@ -15,6 +15,11 @@
|
||||
*/
|
||||
|
||||
import '@backstage/backend-common';
|
||||
import {
|
||||
ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE,
|
||||
ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID,
|
||||
ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
import { CatalogClusterLocator } from './CatalogClusterLocator';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { ClusterDetails } from '../types/types';
|
||||
@@ -24,14 +29,14 @@ const mockCatalogApi = {
|
||||
getEntities: async () => ({
|
||||
items: [
|
||||
{
|
||||
apiVersion: 'version',
|
||||
kind: 'User',
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Resource',
|
||||
metadata: {
|
||||
annotations: {
|
||||
'kubernetes.io/api-server': 'https://apiserver.com',
|
||||
'kubernetes.io/api-server-certificate-authority': 'caData',
|
||||
'kubernetes.io/auth-provider': 'oidc',
|
||||
'kubernetes.io/oidc-token-provider': 'google',
|
||||
[ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: 'google',
|
||||
'kubernetes.io/skip-metrics-lookup': 'true',
|
||||
'kubernetes.io/skip-tls-verify': 'true',
|
||||
'kubernetes.io/dashboard-url': 'my-url',
|
||||
@@ -42,16 +47,16 @@ const mockCatalogApi = {
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: 'version',
|
||||
kind: 'User',
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Resource',
|
||||
metadata: {
|
||||
annotations: {
|
||||
'kubernetes.io/api-server': 'https://apiserver.com',
|
||||
'kubernetes.io/api-server-certificate-authority': 'caData',
|
||||
'kubernetes.io/auth-provider': 'aws',
|
||||
'kubernetes.io/aws-assume-role': 'my-role',
|
||||
'kubernetes.io/aws-external-id': 'my-id',
|
||||
'kubernetes.io/oidc-token-provider': 'google',
|
||||
[ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE]: 'my-role',
|
||||
[ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID]: 'my-id',
|
||||
[ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: 'google',
|
||||
'kubernetes.io/dashboard-url': 'my-url',
|
||||
'kubernetes.io/dashboard-app': 'my-app',
|
||||
},
|
||||
@@ -92,7 +97,16 @@ describe('CatalogClusterLocator', () => {
|
||||
url: 'https://apiserver.com',
|
||||
caData: 'caData',
|
||||
authProvider: 'oidc',
|
||||
authMetadata: { oidcTokenProvider: 'google' },
|
||||
authMetadata: {
|
||||
'kubernetes.io/api-server': 'https://apiserver.com',
|
||||
'kubernetes.io/api-server-certificate-authority': 'caData',
|
||||
'kubernetes.io/auth-provider': 'oidc',
|
||||
[ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: 'google',
|
||||
'kubernetes.io/skip-metrics-lookup': 'true',
|
||||
'kubernetes.io/skip-tls-verify': 'true',
|
||||
'kubernetes.io/dashboard-url': 'my-url',
|
||||
'kubernetes.io/dashboard-app': 'my-app',
|
||||
},
|
||||
skipMetricsLookup: true,
|
||||
skipTLSVerify: true,
|
||||
dashboardUrl: 'my-url',
|
||||
@@ -112,9 +126,14 @@ describe('CatalogClusterLocator', () => {
|
||||
caData: 'caData',
|
||||
authProvider: 'aws',
|
||||
authMetadata: {
|
||||
assumeRole: 'my-role',
|
||||
externalId: 'my-id',
|
||||
oidcTokenProvider: 'google',
|
||||
'kubernetes.io/api-server': 'https://apiserver.com',
|
||||
'kubernetes.io/api-server-certificate-authority': 'caData',
|
||||
'kubernetes.io/auth-provider': 'aws',
|
||||
[ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE]: 'my-role',
|
||||
[ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID]: 'my-id',
|
||||
[ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: 'google',
|
||||
'kubernetes.io/dashboard-url': 'my-url',
|
||||
'kubernetes.io/dashboard-app': 'my-app',
|
||||
},
|
||||
skipMetricsLookup: false,
|
||||
skipTLSVerify: false,
|
||||
|
||||
@@ -20,13 +20,10 @@ import {
|
||||
ANNOTATION_KUBERNETES_API_SERVER,
|
||||
ANNOTATION_KUBERNETES_API_SERVER_CA,
|
||||
ANNOTATION_KUBERNETES_AUTH_PROVIDER,
|
||||
ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER,
|
||||
ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP,
|
||||
ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY,
|
||||
ANNOTATION_KUBERNETES_DASHBOARD_URL,
|
||||
ANNOTATION_KUBERNETES_DASHBOARD_APP,
|
||||
ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID,
|
||||
ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
|
||||
export class CatalogClusterLocator implements KubernetesClustersSupplier {
|
||||
@@ -57,10 +54,6 @@ export class CatalogClusterLocator implements KubernetesClustersSupplier {
|
||||
filter: [filter],
|
||||
});
|
||||
return clusters.items.map(entity => {
|
||||
const oidcTokenProvider =
|
||||
entity.metadata.annotations?.[
|
||||
ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER
|
||||
];
|
||||
const clusterDetails: ClusterDetails = {
|
||||
name: entity.metadata.name,
|
||||
url: entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER]!,
|
||||
@@ -68,7 +61,7 @@ export class CatalogClusterLocator implements KubernetesClustersSupplier {
|
||||
entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER_CA]!,
|
||||
authProvider:
|
||||
entity.metadata.annotations![ANNOTATION_KUBERNETES_AUTH_PROVIDER]!,
|
||||
...(oidcTokenProvider && { authMetadata: { oidcTokenProvider } }),
|
||||
...{ authMetadata: entity.metadata.annotations },
|
||||
skipMetricsLookup:
|
||||
entity.metadata.annotations![
|
||||
ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP
|
||||
@@ -83,23 +76,6 @@ export class CatalogClusterLocator implements KubernetesClustersSupplier {
|
||||
entity.metadata.annotations![ANNOTATION_KUBERNETES_DASHBOARD_APP]!,
|
||||
};
|
||||
|
||||
if (clusterDetails.authProvider === 'aws') {
|
||||
return {
|
||||
...clusterDetails,
|
||||
authMetadata: {
|
||||
assumeRole:
|
||||
entity.metadata.annotations![
|
||||
ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE
|
||||
]!,
|
||||
externalId:
|
||||
entity.metadata.annotations![
|
||||
ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID
|
||||
]!,
|
||||
...clusterDetails.authMetadata,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return clusterDetails;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
import '@backstage/backend-common';
|
||||
import { ConfigReader, Config } from '@backstage/config';
|
||||
import {
|
||||
ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE,
|
||||
ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
import { ConfigClusterLocator } from './ConfigClusterLocator';
|
||||
import { ClusterDetails } from '../types/types';
|
||||
|
||||
@@ -160,7 +164,7 @@ describe('ConfigClusterLocator', () => {
|
||||
url: 'http://localhost:8081',
|
||||
authProvider: 'aws',
|
||||
authMetadata: {
|
||||
assumeRole: 'SomeRole',
|
||||
[ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE]: 'SomeRole',
|
||||
},
|
||||
skipTLSVerify: true,
|
||||
skipMetricsLookup: false,
|
||||
@@ -172,8 +176,8 @@ describe('ConfigClusterLocator', () => {
|
||||
url: 'http://localhost:8081',
|
||||
authProvider: 'aws',
|
||||
authMetadata: {
|
||||
assumeRole: 'SomeRole',
|
||||
externalId: 'SomeExternalId',
|
||||
[ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE]: 'SomeRole',
|
||||
[ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID]: 'SomeExternalId',
|
||||
},
|
||||
skipTLSVerify: true,
|
||||
skipMetricsLookup: false,
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
*/
|
||||
|
||||
import { Config } from '@backstage/config';
|
||||
import {
|
||||
ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE,
|
||||
ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID,
|
||||
ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
import { ClusterDetails, KubernetesClustersSupplier } from '../types/types';
|
||||
|
||||
export class ConfigClusterLocator implements KubernetesClustersSupplier {
|
||||
@@ -75,8 +80,12 @@ export class ConfigClusterLocator implements KubernetesClustersSupplier {
|
||||
|
||||
return {
|
||||
authMetadata: {
|
||||
...(assumeRole && { assumeRole }),
|
||||
...(externalId && { externalId }),
|
||||
...(assumeRole && {
|
||||
[ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE]: assumeRole,
|
||||
}),
|
||||
...(externalId && {
|
||||
[ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID]: externalId,
|
||||
}),
|
||||
...clusterDetails.authMetadata,
|
||||
},
|
||||
...clusterDetails,
|
||||
@@ -90,7 +99,7 @@ export class ConfigClusterLocator implements KubernetesClustersSupplier {
|
||||
|
||||
return {
|
||||
authMetadata: {
|
||||
oidcTokenProvider,
|
||||
[ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: oidcTokenProvider,
|
||||
...clusterDetails.authMetadata,
|
||||
},
|
||||
...clusterDetails,
|
||||
|
||||
+8
-4
@@ -13,8 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import {
|
||||
ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE,
|
||||
ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
import { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';
|
||||
|
||||
let presign = jest.fn(async () => ({
|
||||
hostname: 'https://example.com',
|
||||
@@ -73,7 +77,7 @@ describe('AwsIamKubernetesAuthTranslator tests', () => {
|
||||
name: 'test-cluster',
|
||||
url: '',
|
||||
authProvider: 'aws',
|
||||
authMetadata: { assumeRole: 'SomeRole' },
|
||||
authMetadata: { [ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE]: 'SomeRole' },
|
||||
});
|
||||
expect((await authPromise).authMetadata!.serviceAccountToken).toEqual(
|
||||
'k8s-aws-v1.aHR0cHM6Ly9odHRwczovL2V4YW1wbGUuY29tL2FzZGY_',
|
||||
@@ -100,8 +104,8 @@ describe('AwsIamKubernetesAuthTranslator tests', () => {
|
||||
url: '',
|
||||
authProvider: 'aws',
|
||||
authMetadata: {
|
||||
assumeRole: 'SomeRole',
|
||||
externalId: 'external-id',
|
||||
[ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE]: 'SomeRole',
|
||||
[ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID]: 'external-id',
|
||||
},
|
||||
});
|
||||
expect((await authPromise).authMetadata!.serviceAccountToken).toEqual(
|
||||
|
||||
+8
-4
@@ -13,8 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ClusterDetails } from '../types/types';
|
||||
import { KubernetesAuthTranslator } from './types';
|
||||
import { fromTemporaryCredentials } from '@aws-sdk/credential-providers';
|
||||
import { SignatureV4 } from '@aws-sdk/signature-v4';
|
||||
import { Sha256 } from '@aws-crypto/sha256-js';
|
||||
@@ -23,6 +21,12 @@ import {
|
||||
DefaultAwsCredentialsManager,
|
||||
} from '@backstage/integration-aws-node';
|
||||
import { Config } from '@backstage/config';
|
||||
import {
|
||||
ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE,
|
||||
ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
import { ClusterDetails } from '../types/types';
|
||||
import { KubernetesAuthTranslator } from './types';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -120,8 +124,8 @@ export class AwsIamKubernetesAuthTranslator
|
||||
clusterDetailsWithAuthToken.authMetadata = {
|
||||
serviceAccountToken: await this.getBearerToken(
|
||||
clusterDetails.name,
|
||||
clusterDetails.authMetadata?.assumeRole,
|
||||
clusterDetails.authMetadata?.externalId,
|
||||
clusterDetails.authMetadata?.[ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE],
|
||||
clusterDetails.authMetadata?.[ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID],
|
||||
),
|
||||
...clusterDetailsWithAuthToken.authMetadata,
|
||||
};
|
||||
|
||||
+6
-2
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER } from '@backstage/plugin-kubernetes-common';
|
||||
import { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';
|
||||
import { ClusterDetails } from '../types/types';
|
||||
|
||||
@@ -28,7 +29,7 @@ describe('OidcKubernetesAuthTranslator tests', () => {
|
||||
it('returns cluster details with auth token', async () => {
|
||||
const details = await at.decorateClusterDetailsWithAuth(
|
||||
{
|
||||
authMetadata: { oidcTokenProvider: 'okta' },
|
||||
authMetadata: { [ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: 'okta' },
|
||||
...baseClusterDetails,
|
||||
},
|
||||
{
|
||||
@@ -50,7 +51,10 @@ describe('OidcKubernetesAuthTranslator tests', () => {
|
||||
it('returns error when token is not included in request body', async () => {
|
||||
await expect(
|
||||
at.decorateClusterDetailsWithAuth(
|
||||
{ authMetadata: { oidcTokenProvider: 'okta' }, ...baseClusterDetails },
|
||||
{
|
||||
authMetadata: { [ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: 'okta' },
|
||||
...baseClusterDetails,
|
||||
},
|
||||
{},
|
||||
),
|
||||
).rejects.toThrow('Auth token not found under oidc.okta in request body');
|
||||
|
||||
+6
-3
@@ -13,10 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER,
|
||||
KubernetesRequestAuth,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
import { KubernetesAuthTranslator } from './types';
|
||||
import { ClusterDetails } from '../types/types';
|
||||
import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -32,7 +34,8 @@ export class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
||||
clusterDetails,
|
||||
);
|
||||
|
||||
const oidcTokenProvider = clusterDetails.authMetadata?.oidcTokenProvider;
|
||||
const oidcTokenProvider =
|
||||
clusterDetails.authMetadata?.[ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER];
|
||||
|
||||
if (!oidcTokenProvider || oidcTokenProvider === '') {
|
||||
throw new Error(
|
||||
|
||||
Reference in New Issue
Block a user