Skip to content

Commit

Permalink
Merge branch 'main' into docs/waf-tf-resources
Browse files Browse the repository at this point in the history
  • Loading branch information
cjobermaier committed May 24, 2024
2 parents f71daab + 7438d63 commit c138e29
Show file tree
Hide file tree
Showing 29 changed files with 408 additions and 77 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/plugin-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ on:
description: 'Full name of the plugin, e.g., vault-plugin-auth-kubernetes'
required: true
type: string
branch:
description: 'Git branch name to use'
required: true
type: string
version:
description: 'Version of the plugin with *NO* "v", e.g., 1.2.3'
required: true
Expand All @@ -21,7 +25,7 @@ jobs:
plugin-update:
runs-on: ubuntu-latest
env:
VAULT_BRANCH: "update/${{ inputs.plugin }}/v${{ inputs.version }}"
VAULT_BRANCH: ${{ inputs.branch }}
REVIEWER: ${{ inputs.reviewer || github.actor }}
steps:
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
Expand Down
3 changes: 3 additions & 0 deletions .release/versions.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

schema = 1
active_versions {
version "1.17.x" {
ce_active = true
}
version "1.16.x" {
ce_active = true
lts = true
Expand Down
4 changes: 4 additions & 0 deletions changelog/26020.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```release-note:improvement
core/activity: Include ACME clients in activity log responses
```

```release-note:improvement
ui: Display ACME clients on a separate page in the UI.
```
1 change: 0 additions & 1 deletion enos/enos-dev-scenario-single-cluster.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ scenario "dev_single_cluster" {
variant.
EOF
module = matrix.artifact == "local" ? "build_local" : local.use_artifactory ? "build_artifactory_package" : "build_crt"
skip_step = matrix.artifact == "zip"

variables {
// Used for all modules
Expand Down
5 changes: 3 additions & 2 deletions ui/app/models/auth-config/kubernetes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ export default AuthConfig.extend({
useOpenAPI: true,
kubernetesHost: attr('string', {
helpText:
'Host must be a host string, a host:port pair, or a URL to the base of the Kubernetes API server',
'Host must be a host string, a host:port pair, or a URL to the base of the Kubernetes API server.',
}),

kubernetesCaCert: attr('string', {
editType: 'file',
helpText: 'PEM encoded CA cert for use by the TLS client used to talk with the Kubernetes API',
helpText:
"Optional PEM encoded CA cert for use by the TLS client used to talk with the Kubernetes API. If it is not set and disable_local_ca_jwt is true, the system's trusted CA certificate pool will be used.",
}),

tokenReviewerJwt: attr('string', {
Expand Down
9 changes: 3 additions & 6 deletions ui/lib/sync/addon/components/secrets/page/overview.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,9 @@
{{/if}}
{{/unless}}

{{#if this.activationError}}
{{#if this.activationErrors}}
{{#unless this.hideError}}
<MessageError
@errorMessage={{this.activationError}}
@onDismiss={{fn (mut this.hideError) true}}
data-test-opt-in-error
/>
<MessageError @errors={{this.activationErrors}} @onDismiss={{fn (mut this.hideError) true}} data-test-opt-in-error />
{{/unless}}
{{/if}}

Expand Down Expand Up @@ -204,6 +200,7 @@
<Secrets::SyncActivationModal
@onClose={{fn (mut this.showActivateSecretsSyncModal) false}}
@onError={{this.onModalError}}
@onConfirm={{this.clearActivationErrors}}
@isHvdManaged={{@isHvdManaged}}
/>
{{/if}}
19 changes: 17 additions & 2 deletions ui/lib/sync/addon/components/secrets/page/overview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { service } from '@ember/service';
import { task } from 'ember-concurrency';
import { action } from '@ember/object';
import Ember from 'ember';
import { DEBUG } from '@glimmer/env';

import type FlashMessageService from 'vault/services/flash-messages';
import type StoreService from 'vault/services/store';
Expand All @@ -34,7 +35,7 @@ export default class SyncSecretsDestinationsPageComponent extends Component<Args
@tracked destinationMetrics: SyncDestinationAssociationMetrics[] = [];
@tracked page = 1;
@tracked showActivateSecretsSyncModal = false;
@tracked activationError: null | string = null;
@tracked activationErrors: null | string[] = null;
// eventually remove when we deal with permissions on activation-features
@tracked hideOptIn = false;
@tracked hideError = false;
Expand All @@ -61,8 +62,22 @@ export default class SyncSecretsDestinationsPageComponent extends Component<Args
}
});

@action
clearActivationErrors() {
this.activationErrors = null;
}

@action
onModalError(errorMsg: string) {
this.activationError = errorMsg;
if (DEBUG) console.error(errorMsg); // eslint-disable-line no-console

const errors = [errorMsg];

if (this.args.isHvdManaged) {
errors.push(
'Secrets Sync is available for Plus tier clusters only. Please check the tier of your cluster to enable Secrets Sync.'
);
}
this.activationErrors = errors;
}
}
4 changes: 4 additions & 0 deletions ui/lib/sync/addon/components/secrets/sync-activation-modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type RouterService from '@ember/routing/router-service';
interface Args {
onClose: () => void;
onError: (errorMessage: string) => void;
onConfirm: () => void;
isHvdManaged: boolean;
}

Expand All @@ -30,6 +31,9 @@ export default class SyncActivationModal extends Component<Args> {
@task
@waitFor
*onFeatureConfirm() {
// clear any previous errors in the parent component
this.args.onConfirm();

// must return null instead of root for non managed cluster.
// child namespaces are not sent.
const namespace = this.args.isHvdManaged ? 'admin' : null;
Expand Down
3 changes: 2 additions & 1 deletion ui/tests/helpers/openapi/expected-auth-attrs.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,8 @@ const kubernetes = {
},
kubernetesCaCert: {
editType: 'string',
helpText: 'PEM encoded CA cert for use by the TLS client used to talk with the API.',
helpText:
"Optional PEM encoded CA cert for use by the TLS client used to talk with the API. If it is not set and disable_local_ca_jwt is true, the system's trusted CA certificate pool will be used.",
fieldGroup: 'default',
label: 'Kubernetes CA Certificate',
type: 'string',
Expand Down
72 changes: 69 additions & 3 deletions ui/tests/integration/components/sync/secrets/page/overview-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { setupEngine } from 'ember-engines/test-support';
import { setupMirage } from 'ember-cli-mirage/test-support';
import { render, click, settled } from '@ember/test-helpers';
import { render, click, settled, findAll } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import syncScenario from 'vault/mirage/scenarios/sync';
import syncHandlers from 'vault/mirage/handlers/sync';
import sinon from 'sinon';
import { PAGE } from 'vault/tests/helpers/sync/sync-selectors';
import { Response } from 'miragejs';
import { dateFormat } from 'core/helpers/date-format';
Expand Down Expand Up @@ -126,6 +127,34 @@ module('Integration | Component | sync | Page::Overview', function (hooks) {

assert.dom(overview.optInBanner.container).doesNotExist('Opt-in banner is not shown');
});

test('it should show activation error if cluster is not Plus tier', async function (assert) {
await this.renderComponent();

this.server.post(
'/sys/activation-flags/secrets-sync/activate',
() => new Response(403, {}, { errors: ['Something bad happened'] })
);

await click(overview.optInBanner.enable);
await click(overview.activationModal.checkbox);
await click(overview.activationModal.confirm);

assert.dom(overview.optInError).exists({ count: 2 }, 'shows the API and custom tier error banners');

const errorBanners = findAll(overview.optInError);

assert.dom(errorBanners[0]).containsText('Something bad happened', 'shows the API error message');

assert
.dom(errorBanners[1])
.containsText(
'Error Secrets Sync is available for Plus tier clusters only. Please check the tier of your cluster to enable Secrets Sync.',
'shows the custom tier-related error message'
);

assert.dom(overview.optInBanner.container).exists('banner is visible so user can try to opt-in again');
});
});

module('user does not have post permissions to activate', function (hooks) {
Expand Down Expand Up @@ -186,15 +215,52 @@ module('Integration | Component | sync | Page::Overview', function (hooks) {
test('it shows an error if activation fails', async function (assert) {
await this.renderComponent();

this.server.post('/sys/activation-flags/secrets-sync/activate', () => new Response(403));
this.server.post(
'/sys/activation-flags/secrets-sync/activate',
() => new Response(403, {}, { errors: ['Something bad happened'] })
);

await click(overview.optInBanner.enable);
await click(overview.activationModal.checkbox);
await click(overview.activationModal.confirm);

assert.dom(overview.optInError).exists('shows an error banner');
assert
.dom(overview.optInError)
.exists({ count: 1 })
.containsText('Something bad happened', 'shows an error banner with error message from the API');
assert.dom(overview.optInBanner.container).exists('banner is visible so user can try to opt-in again');
});

test('it should clear activation errors when the user tries to opt-in again', async function (assert) {
// don't worry about transitioning the route in this test
sinon.stub(this.owner.lookup('service:router'), 'refresh');

await this.renderComponent();

let callCount = 0;

// first call fails, second call succeeds
this.server.post('/sys/activation-flags/secrets-sync/activate', () => {
callCount++;
if (callCount === 1) {
return new Response(403, {}, { errors: ['Something bad happened'] });
} else {
return {};
}
});

await click(overview.optInBanner.enable);
await click(overview.activationModal.checkbox);
await click(overview.activationModal.confirm);

assert.dom(overview.optInError).exists('shows an error banner');

await click(overview.optInBanner.enable);
await click(overview.activationModal.checkbox);
await click(overview.activationModal.confirm);

assert.dom(overview.optInError).doesNotExist('error banner is cleared upon trying to opt-in again');
});
});

module('secrets sync is not activated and license does not have secrets sync', function (hooks) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ module('Integration | Component | Secrets::SyncActivationModal', function (hooks
hooks.beforeEach(function () {
this.onClose = sinon.stub();
this.onError = sinon.stub();
this.onConfirm = sinon.stub();
this.isHvdManaged = false;

this.renderComponent = async () => {
await render(
hbs`
<Secrets::SyncActivationModal @onClose={{this.onClose}} @onError={{this.onError}} @isHvdManaged={{this.isHvdManaged}}/>
<Secrets::SyncActivationModal @onClose={{this.onClose}} @onError={{this.onError}} @onConfirm={{this.onConfirm}} @isHvdManaged={{this.isHvdManaged}}/>
`,
{ owner: this.engine }
);
Expand Down Expand Up @@ -70,6 +71,15 @@ module('Integration | Component | Secrets::SyncActivationModal', function (hooks
this.refreshStub = sinon.stub(router, 'refresh');
});

test('it calls onConfirm', async function (assert) {
await this.renderComponent();

await click(SELECTORS.checkbox);
await click(SELECTORS.confirm);

assert.true(this.onConfirm.called);
});

module('success', function (hooks) {
hooks.beforeEach(function () {
this.server.post('/sys/activation-flags/secrets-sync/activate', () => {
Expand Down
17 changes: 13 additions & 4 deletions website/content/api-docs/auth/aws.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ custom endpoints to talk to AWS APIs. The instance identity document
fetched from the PKCS#7 signature will provide the EC2 instance ID. The
credentials configured using this endpoint will be used to query the status
of the instances via DescribeInstances API. If static credentials are not
provided using this endpoint, then the credentials will be retrieved from
provided using this endpoint, or [plugin workload identity federation](/vault/docs/auth/aws#plugin-workload-identity-federation-wif)
credentials are also not provided, then the credentials will be retrieved from
the environment variables `AWS_ACCESS_KEY`, `AWS_SECRET_KEY` and
`AWS_REGION` respectively. If the credentials are still not found and if the
method is configured on an EC2 instance with metadata querying
Expand All @@ -53,9 +54,17 @@ capabilities, the credentials are fetched automatically.
access to `iam:GetInstanceProfile`. If, however, an alternate sts
configuration is set for the target account, then the credentials must be
permissioned to call `sts:AssumeRole` on the configured role, and that role
must have the permissions described here.
must have the permissions described here. Mutually exclusive with `identity_token_audience`.
- `secret_key` `(string: "")` - AWS Secret key with permissions to query AWS
APIs.
- `role_arn` `(string: "")` – <EnterpriseAlert product="vault" inline /> Role ARN to assume
for plugin workload identity federation. Required with `identity_token_audience`.
- `identity_token_audience` `(string: "")` - <EnterpriseAlert product="vault" inline /> The
audience claim value for plugin identity tokens. Must match an allowed audience configured
for the target [IAM OIDC identity provider](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html#manage-oidc-provider-console).
Mutually exclusive with `access_key`.
- `identity_token_ttl` `(string/int: 3600)` - <EnterpriseAlert product="vault" inline /> The
TTL of generated tokens. Defaults to 1 hour. Uses [duration format strings](/vault/docs/concepts/duration-format).
- `endpoint` `(string: "")` - URL to override the default generated endpoint for
making AWS EC2 API calls.
- `iam_endpoint` `(string: "")` - URL to override the default generated endpoint
Expand Down Expand Up @@ -208,8 +217,8 @@ This configures the way that Vault interacts with the
is used. When `unique_id` is selected, the [IAM Unique
ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers#identifiers-unique-ids)
of the IAM principal (either the user or role) is used as the identity alias
name. When `canonical_arn` is selected, the role ARN returned by the `sts:GetCallerIdentity`call
will be used. This will be `arn:aws:iam::<account_id>:role/<role name>`. When `full_arn` is selected,
name. When `canonical_arn` is selected, the role ARN returned by the `sts:GetCallerIdentity`call
will be used. This will be `arn:aws:iam::<account_id>:role/<role name>`. When `full_arn` is selected,
the ARN returned by the `sts:GetCallerIdentity` call is used as the alias name. This is either
`arn:aws:iam::<account_id>:user/<optional_path/><user_name>` or
`arn:aws:sts::<account_id>:assumed-role/<role_name_without_path>/<role_session_name>`.
Expand Down
Loading

0 comments on commit c138e29

Please sign in to comment.