Skip to content

Commit

Permalink
Merge branch 'VAULT-32686-plugin-register-with-artifact-stubs' of git…
Browse files Browse the repository at this point in the history
…hub.com:hashicorp/vault into VAULT-32686-plugin-register-with-artifact-stubs
  • Loading branch information
thyton committed Dec 12, 2024
2 parents 8daeb2a + 468a7f3 commit 0a4b21b
Show file tree
Hide file tree
Showing 211 changed files with 5,526 additions and 1,974 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
jobs:
bench:
name: Bench
if: github.base_ref == 'main'
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
Expand Down
8 changes: 4 additions & 4 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
/plugins/ @hashicorp/vault-ecosystem
/vault/plugin_catalog.go @hashicorp/vault-ecosystem

/website/content/ @hashicorp/vault-education-approvers
/website/content/docs/plugin-portal.mdx @hashicorp/vault-education-approvers
# Content on developer.hashicorp.com
/website/ @hashicorp/vault-education-approvers

# Plugin docs
/website/content/docs/plugins/ @hashicorp/vault-ecosystem @hashicorp/vault-education-approvers
/website/content/docs/upgrading/plugins.mdx @hashicorp/vault-ecosystem @hashicorp/vault-education-approvers
/website/content/docs/plugins/ @hashicorp/vault-ecosystem
/website/content/docs/upgrading/plugins.mdx @hashicorp/vault-ecosystem

/ui/ @hashicorp/vault-ui
# UI code related to Vault's JWT/OIDC auth method and OIDC provider.
Expand Down
35 changes: 20 additions & 15 deletions api/sys_health.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ func (c *Sys) HealthWithContext(ctx context.Context) (*HealthResponse, error) {
r.Params.Add("standbycode", "299")
r.Params.Add("drsecondarycode", "299")
r.Params.Add("performancestandbycode", "299")
r.Params.Add("removedcode", "299")
r.Params.Add("haunhealthycode", "299")

resp, err := c.c.rawRequestWithContext(ctx, r)
if err != nil {
Expand All @@ -38,19 +40,22 @@ func (c *Sys) HealthWithContext(ctx context.Context) (*HealthResponse, error) {
}

type HealthResponse struct {
Initialized bool `json:"initialized"`
Sealed bool `json:"sealed"`
Standby bool `json:"standby"`
PerformanceStandby bool `json:"performance_standby"`
ReplicationPerformanceMode string `json:"replication_performance_mode"`
ReplicationDRMode string `json:"replication_dr_mode"`
ServerTimeUTC int64 `json:"server_time_utc"`
Version string `json:"version"`
ClusterName string `json:"cluster_name,omitempty"`
ClusterID string `json:"cluster_id,omitempty"`
LastWAL uint64 `json:"last_wal,omitempty"`
Enterprise bool `json:"enterprise"`
EchoDurationMillis int64 `json:"echo_duration_ms"`
ClockSkewMillis int64 `json:"clock_skew_ms"`
ReplicationPrimaryCanaryAgeMillis int64 `json:"replication_primary_canary_age_ms"`
Initialized bool `json:"initialized"`
Sealed bool `json:"sealed"`
Standby bool `json:"standby"`
PerformanceStandby bool `json:"performance_standby"`
ReplicationPerformanceMode string `json:"replication_performance_mode"`
ReplicationDRMode string `json:"replication_dr_mode"`
ServerTimeUTC int64 `json:"server_time_utc"`
Version string `json:"version"`
ClusterName string `json:"cluster_name,omitempty"`
ClusterID string `json:"cluster_id,omitempty"`
LastWAL uint64 `json:"last_wal,omitempty"`
Enterprise bool `json:"enterprise"`
EchoDurationMillis int64 `json:"echo_duration_ms"`
ClockSkewMillis int64 `json:"clock_skew_ms"`
ReplicationPrimaryCanaryAgeMillis int64 `json:"replication_primary_canary_age_ms"`
RemovedFromCluster *bool `json:"removed_from_cluster,omitempty"`
HAConnectionHealthy *bool `json:"ha_connection_healthy,omitempty"`
LastRequestForwardingHeartbeatMillis int64 `json:"last_request_forwarding_heartbeat_ms,omitempty"`
}
40 changes: 37 additions & 3 deletions builtin/credential/cert/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
Expand Down Expand Up @@ -39,6 +38,7 @@ import (
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/cryptoutil"
"github.com/hashicorp/vault/sdk/helper/tokenutil"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/vault"
Expand Down Expand Up @@ -658,7 +658,7 @@ func TestBackend_NonCAExpiry(t *testing.T) {
template.IPAddresses = []net.IP{parsedIP}

// Private key for CA cert
caPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
caPrivateKey, err := cryptoutil.GenerateRSAKey(rand.Reader, 2048)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -726,7 +726,7 @@ func TestBackend_NonCAExpiry(t *testing.T) {
template.SerialNumber = big.NewInt(5678)

template.KeyUsage = x509.KeyUsage(x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign)
issuedPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
issuedPrivateKey, err := cryptoutil.GenerateRSAKey(rand.Reader, 2048)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -1317,6 +1317,8 @@ func TestBackend_ext_singleCert(t *testing.T) {
testAccStepLoginWithMetadata(t, connState, "web", map[string]string{"2-1-1-1": "A UTF8String Extension"}, true),
testAccStepCert(t, "web", ca, "foo", allowed{metadata_ext: "1.2.3.45"}, false),
testAccStepLoginWithMetadata(t, connState, "web", map[string]string{}, true),
testAccStepSetConfig(t, config{EnableMetadataOnFailures: true}, connState),
testAccStepReadConfig(t, config{EnableMetadataOnFailures: true}, connState),
},
})
}
Expand Down Expand Up @@ -1728,6 +1730,7 @@ func testAccStepSetConfig(t *testing.T, conf config, connState tls.ConnectionSta
ConnState: &connState,
Data: map[string]interface{}{
"enable_identity_alias_metadata": conf.EnableIdentityAliasMetadata,
"enable_metadata_on_failures": conf.EnableMetadataOnFailures,
},
}
}
Expand All @@ -1752,6 +1755,20 @@ func testAccStepReadConfig(t *testing.T, conf config, connState tls.ConnectionSt
t.Fatalf("bad: expected enable_identity_alias_metadata to be %t, got %t", conf.EnableIdentityAliasMetadata, b)
}

metaValueRaw, ok := resp.Data["enable_metadata_on_failures"]
if !ok {
t.Fatalf("enable_metadata_on_failures not found in response")
}

metaValue, ok := metaValueRaw.(bool)
if !ok {
t.Fatalf("bad: expected enable_metadata_on_failures to be a bool")
}

if metaValue != conf.EnableMetadataOnFailures {
t.Fatalf("bad: expected enable_metadata_on_failures to be %t, got %t", conf.EnableMetadataOnFailures, metaValue)
}

return nil
},
}
Expand Down Expand Up @@ -1936,6 +1953,23 @@ func testAccStepCert(t *testing.T, name string, cert []byte, policies string, te
return testAccStepCertWithExtraParams(t, name, cert, policies, testData, expectError, nil)
}

func testStepEnableMetadataFailures() logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.UpdateOperation,
Path: "config",
ErrorOk: false,
Data: map[string]interface{}{
"enable_metadata_on_failures": true,
},
Check: func(resp *logical.Response) error {
if resp != nil && resp.IsError() {
return fmt.Errorf("expected nil response got a response error: %v", resp)
}
return nil
},
}
}

func testAccStepCertWithExtraParams(t *testing.T, name string, cert []byte, policies string, testData allowed, expectError bool, extraParams map[string]interface{}) logicaltest.TestStep {
data := map[string]interface{}{
"certificate": string(cert),
Expand Down
10 changes: 10 additions & 0 deletions builtin/credential/cert/path_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ func pathConfig(b *backend) *framework.Path {
Default: defaultRoleCacheSize,
Description: `The size of the in memory role cache`,
},
"enable_metadata_on_failures": {
Type: framework.TypeBool,
Default: false,
Description: `If set, metadata of the client certificate will be returned on authentication failures.`,
},
},

Operations: map[logical.Operation]framework.OperationHandler{
Expand Down Expand Up @@ -87,6 +92,9 @@ func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, dat
}
config.RoleCacheSize = cacheSize
}
if enableMetadataOnFailures, ok := data.GetOk("enable_metadata_on_failures"); ok {
config.EnableMetadataOnFailures = enableMetadataOnFailures.(bool)
}
if err := b.storeConfig(ctx, req.Storage, config); err != nil {
return nil, err
}
Expand All @@ -104,6 +112,7 @@ func (b *backend) pathConfigRead(ctx context.Context, req *logical.Request, d *f
"enable_identity_alias_metadata": cfg.EnableIdentityAliasMetadata,
"ocsp_cache_size": cfg.OcspCacheSize,
"role_cache_size": cfg.RoleCacheSize,
"enable_metadata_on_failures": cfg.EnableMetadataOnFailures,
}

return &logical.Response{
Expand Down Expand Up @@ -133,4 +142,5 @@ type config struct {
EnableIdentityAliasMetadata bool `json:"enable_identity_alias_metadata"`
OcspCacheSize int `json:"ocsp_cache_size"`
RoleCacheSize int `json:"role_cache_size"`
EnableMetadataOnFailures bool `json:"enable_metadata_on_failures"`
}
64 changes: 61 additions & 3 deletions builtin/credential/cert/path_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,20 @@ func (b *backend) loginPathWrapper(wrappedOp func(ctx context.Context, req *logi
}

func (b *backend) pathLoginResolveRole(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
config, err := b.Config(ctx, req.Storage)
if err != nil {
return nil, err
}
if b.configUpdated.Load() {
b.updatedConfig(config)
}

var matched *ParsedCert

if verifyResp, resp, err := b.verifyCredentials(ctx, req, data); err != nil {
return nil, err
} else if resp != nil {
return resp, nil
return certAuthLoginFailureResponse(config, resp, req), nil
} else {
matched = verifyResp
}
Expand Down Expand Up @@ -118,7 +126,7 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, data *fra
if verifyResp, resp, err := b.verifyCredentials(ctx, req, data); err != nil {
return nil, err
} else if resp != nil {
return resp, nil
return certAuthLoginFailureResponse(config, resp, req), nil
} else {
matched = verifyResp
}
Expand Down Expand Up @@ -181,6 +189,56 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, data *fra
}, nil
}

func certAuthLoginFailureResponse(config *config, resp *logical.Response, req *logical.Request) *logical.Response {
if !config.EnableMetadataOnFailures || !resp.IsError() {
return resp
}
var initialErrMsg string
if err := resp.Error(); err != nil {
initialErrMsg = err.Error()
}

clientCert, exists := getClientCert(req)
if !exists {
return logical.ErrorResponse("no client certificate found\n" + initialErrMsg)
}

// Trim these values as they can be anything from any sort of failed certificate
// and we don't want to expose audit entries to randomly large strings.
const maxChars = 100
metadata := map[string]string{
"common_name": trimToMaxChars(clientCert.Subject.CommonName, maxChars),
"serial_number": trimToMaxChars(clientCert.SerialNumber.String(), maxChars),
"subject_key_id": trimToMaxChars(certutil.GetHexFormatted(clientCert.SubjectKeyId, ":"), maxChars),
"authority_key_id": trimToMaxChars(certutil.GetHexFormatted(clientCert.AuthorityKeyId, ":"), maxChars),
}

return logical.ErrorResponseWithData(metadata, initialErrMsg)
}

func getClientCert(req *logical.Request) (*x509.Certificate, bool) {
if req == nil || req.Connection == nil || req.Connection.ConnState == nil || req.Connection.ConnState.PeerCertificates == nil {
return nil, false
}
clientCerts := req.Connection.ConnState.PeerCertificates
if len(clientCerts) == 0 {
return nil, false
}
clientCert := clientCerts[0]
if clientCert == nil || clientCert.IsCA {
return nil, false
}
return clientCert, true
}

func trimToMaxChars(formatted string, maxSize int) string {
if len(formatted) > maxSize {
return formatted[:maxSize-3] + "..."
}

return formatted
}

func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
config, err := b.Config(ctx, req.Storage)
if err != nil {
Expand All @@ -195,7 +253,7 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *f
if verifyResp, resp, err := b.verifyCredentials(ctx, req, d); err != nil {
return nil, err
} else if resp != nil {
return resp, nil
return certAuthLoginFailureResponse(config, resp, req), nil
} else {
matched = verifyResp
}
Expand Down
Loading

0 comments on commit 0a4b21b

Please sign in to comment.