Skip to content

Commit a1c888e

Browse files
authored
Merge branch 'main' into chore/vault-license-pr-2026-03-11
2 parents a115500 + 8f77425 commit a1c888e

File tree

501 files changed

+13519
-2646
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

501 files changed

+13519
-2646
lines changed

.github/actions/metadata/action.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ runs:
156156
if [ "$is_enterprise_repo" = 'true' ]; then
157157
base_ref='${{ github.event.pull_request.base.ref || github.event.base_ref || github.ref_name || github.event.branch || github.ref }}'
158158
is_ent_repo='true'
159+
is_ent_branch='true'
159160
is_ce_in_enterprise=$([[ $base_ref == ce/* ]] && echo "true" || echo "false")
160161
if [ "$is_ce_in_enterprise" = 'true' ]; then
161162
is_enterprise="false"
@@ -192,7 +193,7 @@ runs:
192193
echo "compute-small=${compute_small}"
193194
echo "go-tags=${go_tags}"
194195
echo "is-ce-in-enterprise=${is_ce_in_enterprise}"
195-
echo "is-ent-branch=${is_enterprise}"
196+
echo "is-ent-branch=${is_ent_branch}"
196197
echo "is-ent-repo=${is_ent_repo}"
197198
echo "vault-version-metadata=${version_metadata}"
198199
} | tee -a "$GITHUB_OUTPUT"

.github/workflows/build.yml

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -392,25 +392,75 @@ jobs:
392392
web-ui-cache-key: ${{ needs.ui.outputs.cache-key }}
393393
secrets: inherit
394394

395+
# Setup HCP input parameters with proper validation
396+
hcp-setup:
397+
runs-on: ubuntu-latest
398+
outputs:
399+
pull-request-number: ${{ steps.pr-logic.outputs.pull-request-number }}
400+
branch-name: ${{ steps.branch-logic.outputs.branch-name }}
401+
steps:
402+
- id: pr-logic
403+
name: Determine pull request number
404+
run: |
405+
echo "Analyzing PR context for event: ${{ github.event_name }}"
406+
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
407+
PR_NUM="${{ github.event.pull_request.number }}"
408+
if [[ -n "$PR_NUM" && "$PR_NUM" != "null" ]]; then
409+
echo "PR context detected, using number: $PR_NUM"
410+
else
411+
echo "PR context but no valid number found, using 0"
412+
PR_NUM="0"
413+
fi
414+
else
415+
PR_NUM="0"
416+
echo "Non-PR context, using fallback value: $PR_NUM"
417+
fi
418+
echo "pull-request-number=$PR_NUM" >> "$GITHUB_OUTPUT"
419+
420+
- id: branch-logic
421+
name: Determine branch name
422+
run: |
423+
echo "Analyzing branch context for event: ${{ github.event_name }}"
424+
if [[ "${{ github.event_name }}" == "schedule" ]]; then
425+
BRANCH="main"
426+
echo "Schedule context, using branch: $BRANCH"
427+
else
428+
BRANCH=""
429+
echo "Non-schedule context, using empty branch"
430+
fi
431+
echo "branch-name=$BRANCH" >> "$GITHUB_OUTPUT"
432+
395433
hcp-image:
434+
# Logic: Run HCP image job if:
435+
# if needs.setup.outputs.is-ent-branch != 'true' then
436+
# false
437+
# elseif needs.setup.outputs.workflow-trigger == 'schedule' then
438+
# true
439+
# elseif needs.setup.outputs.workflow-trigger == 'pull_request' and (
440+
# contains(fromJSON(needs.setup.outputs.changed-files).groups, 'hcp') or
441+
# contains(fromJSON(needs.setup.outputs.labels), 'hcp/build-image') or
442+
# contains(fromJSON(needs.setup.outputs.labels), 'hcp/test')
443+
# ) then
444+
# true
445+
# end
396446
if: |
397-
needs.setup.outputs.is-ent-branch == 'true' && (
398-
needs.setup.outputs.workflow-trigger == 'schedule' ||
447+
( needs.setup.outputs.is-ent-branch != 'true' ) && false ||
448+
( needs.setup.outputs.workflow-trigger == 'schedule' ) && true ||
399449
( needs.setup.outputs.workflow-trigger == 'pull_request' &&
400-
(
450+
( contains(fromJSON(needs.setup.outputs.changed-files).groups, 'hcp') ||
401451
contains(fromJSON(needs.setup.outputs.changed-files).groups, 'hcp') ||
402452
contains(fromJSON(needs.setup.outputs.labels), 'hcp/build-image') ||
403453
contains(fromJSON(needs.setup.outputs.labels), 'hcp/test')
404454
)
405-
)
406-
)
455+
) && true
407456
needs:
408457
- setup
409458
- artifacts-ent
459+
- hcp-setup
410460
uses: ./.github/workflows/build-hcp-image.yml
411461
with:
412-
pull-request: ${{ needs.setup.outputs.workflow-trigger == 'pull_request' && github.event.pull_request && github.event.pull_request.number || '' }}
413-
branch: ${{ needs.setup.outputs.workflow-trigger == 'schedule' && 'main' || '' }}
462+
pull-request: ${{ fromJSON(needs.hcp-setup.outputs.pull-request-number) }}
463+
branch: ${{ needs.hcp-setup.outputs.branch-name }}
414464
create-aws-image: true
415465
create-azure-image: false
416466
hcp-environment: int

.github/workflows/test-run-enos-scenario-matrix.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ jobs:
200200
echo 'ENOS_VAR_verify_ldap_secrets_engine=false'
201201
echo 'ENOS_VAR_verify_log_secrets=true'
202202
} | tee -a "$GITHUB_ENV"
203+
- uses: ./.github/actions/set-up-go
204+
with:
205+
github-token: ${{ steps.secrets.outputs.github-token }}
206+
- uses: ./.github/actions/install-tools
203207
- uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4.0.0
204208
with:
205209
# the Terraform wrapper will break Terraform execution in Enos because

.github/workflows/test-run-enos-scenario.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ jobs:
6464
- uses: ./.github/actions/set-up-go
6565
with:
6666
github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
67+
# Install additional tools like gotestsum that are required for Enos scenarios
68+
- uses: ./.github/actions/install-tools
6769
- name: Configure Git
6870
run: git config --global url."https://${{ secrets.ELEVATED_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com"
6971
- name: Set up node

.hooks/pre-push

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545

4646
set -eou pipefail
4747

48+
# We need extglob in order to parse remote_url_is_enterprise
49+
shopt -s extglob
50+
4851
# fail takes two arguments. The first is the failure reasons and the second is
4952
# an explanation. Both will be written to STDERR. The script will then exit 1.
5053
fail() {
@@ -60,7 +63,7 @@ fail() {
6063
# that of hashicorp/vault-enterprise, otherwise it returns 1.
6164
remote_url_is_enterprise() {
6265
case "$1" in
63-
git@github.com:hashicorp/vault-enterprise* | https://github.com/hashicorp/vault-enterprise*)
66+
?(ssh://)git@github.com@(:|/)hashicorp/vault-enterprise?(.git) | https://github.com/hashicorp/vault-enterprise?(.git))
6467
return 0
6568
;;
6669
*)

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ ENV NAME=$NAME
3737
# Create a non-root user to run the software.
3838
RUN addgroup ${NAME} && adduser -S -G ${NAME} ${NAME}
3939

40-
RUN apk add --no-cache libcap su-exec dumb-init tzdata
40+
# NOTE: zlib is only here to resolve ALPINE-CVE-2026-27171, it can be removed
41+
# when when our Alpine release is >= 3.23.4
42+
RUN apk update && apk add --upgrade --no-cache libcap su-exec dumb-init tzdata zlib
4143

4244
COPY dist/$TARGETOS/$TARGETARCH/$BIN_NAME /bin/
4345

Makefile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,6 @@ proto: check-tools-external
239239
$(SED_CMD) -e 's/Id/ID/' -e 's/SPDX-License-IDentifier/SPDX-License-Identifier/' vault/request_forwarding_service.pb.go
240240
$(SED_CMD) -e 's/Idp/IDP/' -e 's/Url/URL/' -e 's/Id/ID/' -e 's/IDentity/Identity/' -e 's/EntityId/EntityID/' -e 's/Api/API/' -e 's/Qr/QR/' -e 's/Totp/TOTP/' -e 's/Mfa/MFA/' -e 's/Pingid/PingID/' -e 's/namespaceId/namespaceID/' -e 's/Ttl/TTL/' -e 's/BoundCidrs/BoundCIDRs/' -e 's/SPDX-License-IDentifier/SPDX-License-Identifier/' helper/identity/types.pb.go helper/identity/mfa/types.pb.go helper/storagepacker/types.pb.go sdk/plugin/pb/backend.pb.go sdk/logical/identity.pb.go vault/activity/activity_log.pb.go
241241

242-
# Enterprise files
243-
$(SED_CMD) -e 's/Idp/IDP/' -e 's/Url/URL/' -e 's/Id/ID/' -e 's/IDentity/Identity/' -e 's/EntityId/EntityID/' -e 's/Api/API/' -e 's/Qr/QR/' -e 's/Totp/TOTP/' -e 's/Mfa/MFA/' -e 's/Pingid/PingID/' -e 's/protobuf:"/sentinel:"" protobuf:"/' -e 's/namespaceId/namespaceID/' -e 's/Ttl/TTL/' -e 's/SPDX-License-IDentifier/SPDX-License-Identifier/' vault/replication_services_ent.pb.go
244-
245242
# This will inject the sentinel struct tags as decorated in the proto files.
246243
protoc-go-inject-tag -input=./helper/identity/types.pb.go
247244
protoc-go-inject-tag -input=./helper/identity/mfa/types.pb.go

api/logical.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,15 @@ func (c *Logical) DeleteWithContext(ctx context.Context, path string) (*Secret,
393393
return c.DeleteWithDataWithContext(ctx, path, nil)
394394
}
395395

396+
func (c *Logical) DeleteRaw(path string) (*Response, error) {
397+
return c.DeleteRawWithContext(context.Background(), path)
398+
}
399+
400+
func (c *Logical) DeleteRawWithContext(ctx context.Context, path string) (*Response, error) {
401+
r := c.c.NewRequest(http.MethodDelete, "/v1/"+path)
402+
return c.c.RawRequestWithContext(ctx, r)
403+
}
404+
396405
func (c *Logical) DeleteWithData(path string, data map[string][]string) (*Secret, error) {
397406
return c.DeleteWithDataWithContext(context.Background(), path, data)
398407
}

api/sys_billing_test.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func TestSys_BillingOverview(t *testing.T) {
3333
currentMonth := resp.Months[0]
3434
require.Equal(t, "2026-01", currentMonth.Month)
3535
require.Equal(t, "2026-01-14T10:49:00Z", currentMonth.UpdatedAt)
36-
require.Len(t, currentMonth.UsageMetrics, 8, "should have all 8 metrics")
36+
require.Len(t, currentMonth.UsageMetrics, 9, "should have all 9 metrics")
3737

3838
// Create a map to verify all expected metrics are present
3939
metricsMap := make(map[string]UsageMetric)
@@ -51,6 +51,7 @@ func TestSys_BillingOverview(t *testing.T) {
5151
"data_protection_calls",
5252
"pki_units",
5353
"managed_keys",
54+
"ssh_units",
5455
}
5556

5657
for _, metricName := range expectedMetrics {
@@ -86,6 +87,10 @@ func TestSys_BillingOverview(t *testing.T) {
8687
require.Equal(t, "external_plugins", externalPluginsMetric.MetricName)
8788
require.NotNil(t, externalPluginsMetric.MetricData)
8889
require.Contains(t, externalPluginsMetric.MetricData, "total")
90+
91+
sshMetric := metricsMap["ssh_units"]
92+
require.Contains(t, sshMetric.MetricData, "total")
93+
require.Contains(t, sshMetric.MetricData, "metric_details")
8994
}
9095

9196
func mockVaultBillingHandler(w http.ResponseWriter, _ *http.Request) {
@@ -200,6 +205,22 @@ const billingOverviewResponse = `{
200205
}
201206
]
202207
}
208+
},
209+
{
210+
"metric_name": "ssh_units",
211+
"metric_data": {
212+
"total": 8.4,
213+
"metric_details": [
214+
{
215+
"type": "otp_units",
216+
"count": 5
217+
},
218+
{
219+
"type": "certificate_units",
220+
"count": 3.4
221+
}
222+
]
223+
}
203224
}
204225
]
205226
},

audit/entry_formatter.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package audit
55

66
import (
77
"context"
8+
"encoding/json"
89
"errors"
910
"fmt"
1011
"maps"
@@ -253,6 +254,46 @@ func clone[V any](s V) (V, error) {
253254
return s2.(V), err
254255
}
255256

257+
// mergeEnterpriseTokenMetadata injects enterprise token fields from a logical.Request
258+
// into the audit auth's Metadata map.
259+
func mergeEnterpriseTokenMetadata(a *auth, req *logical.Request) error {
260+
if a == nil || req == nil {
261+
return nil
262+
}
263+
264+
if req.EnterpriseTokenMetadata == "" &&
265+
req.EnterpriseTokenIssuer == "" &&
266+
len(req.EnterpriseTokenAudience) == 0 &&
267+
len(req.EnterpriseTokenAuthorizationDetails) == 0 {
268+
return nil
269+
}
270+
271+
if a.Metadata == nil {
272+
a.Metadata = make(map[string]string)
273+
}
274+
if req.EnterpriseTokenMetadata != "" {
275+
a.Metadata["enterprise_token_metadata"] = req.EnterpriseTokenMetadata
276+
}
277+
if req.EnterpriseTokenIssuer != "" {
278+
a.Metadata["enterprise_token_issuer"] = req.EnterpriseTokenIssuer
279+
}
280+
if len(req.EnterpriseTokenAudience) > 0 {
281+
audJSON, err := json.Marshal(req.EnterpriseTokenAudience)
282+
if err != nil {
283+
return fmt.Errorf("unable to marshal enterprise token audience for audit: %w", err)
284+
}
285+
a.Metadata["enterprise_token_audience"] = string(audJSON)
286+
}
287+
if len(req.EnterpriseTokenAuthorizationDetails) > 0 {
288+
authzJSON, err := json.Marshal(req.EnterpriseTokenAuthorizationDetails)
289+
if err != nil {
290+
return fmt.Errorf("unable to marshal enterprise token authorization details for audit: %w", err)
291+
}
292+
a.Metadata["enterprise_token_authorization_details"] = string(authzJSON)
293+
}
294+
return nil
295+
}
296+
256297
// newAuth takes a logical.Auth and the number of remaining client token uses
257298
// (which should be supplied from the logical.Request's client token), and creates
258299
// an audit auth.
@@ -281,6 +322,18 @@ func newAuth(input *logical.Auth, tokenRemainingUses int) (*auth, error) {
281322
return nil, fmt.Errorf("unable to clone logical auth: metadata: %w", err)
282323
}
283324

325+
if input.ActorEntityID != "" || input.ActorEntityName != "" {
326+
if metadata == nil {
327+
metadata = make(map[string]string)
328+
}
329+
if input.ActorEntityID != "" {
330+
metadata["actor_entity_id"] = input.ActorEntityID
331+
}
332+
if input.ActorEntityName != "" {
333+
metadata["actor_entity_name"] = input.ActorEntityName
334+
}
335+
}
336+
284337
policies, err := clone(input.Policies)
285338
if err != nil {
286339
return nil, fmt.Errorf("unable to clone logical auth: policies: %w", err)
@@ -535,6 +588,10 @@ func (f *entryFormatter) createEntry(ctx context.Context, a *Event) (*entry, err
535588
return nil, fmt.Errorf("cannot convert auth: %w", err)
536589
}
537590

591+
if err := mergeEnterpriseTokenMetadata(auth, data.Request); err != nil {
592+
return nil, err
593+
}
594+
538595
req, err := newRequest(data.Request, ns)
539596
if err != nil {
540597
return nil, fmt.Errorf("cannot convert request: %w", err)
@@ -548,6 +605,12 @@ func (f *entryFormatter) createEntry(ctx context.Context, a *Event) (*entry, err
548605
return nil, fmt.Errorf("cannot convert response: %w", err)
549606
}
550607

608+
if resp != nil && resp.Auth != nil {
609+
if err := mergeEnterpriseTokenMetadata(resp.Auth, data.Request); err != nil {
610+
return nil, err
611+
}
612+
}
613+
551614
// If the plugin's response contained any additional audit request fields,
552615
// lets populate them on our original request.
553616
if data.Response != nil && data.Response.SupplementalAuditRequestData != nil {

0 commit comments

Comments
 (0)