Skip to content

Commit

Permalink
backport of commit fd9e113 (#26512)
Browse files Browse the repository at this point in the history
Co-authored-by: Scott Miller <[email protected]>
  • Loading branch information
1 parent c7cae8e commit 8645e74
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 2 deletions.
81 changes: 81 additions & 0 deletions builtin/logical/pki/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,87 @@ func TestIntegration_AutoIssuer(t *testing.T) {
require.Equal(t, issuerIdOneReimported, resp.Data["default"])
}

// TestLDAPAiaCrlUrls validates we can properly handle CRL urls that are ldap based.
func TestLDAPAiaCrlUrls(t *testing.T) {
t.Parallel()

coreConfig := &vault.CoreConfig{
LogicalBackends: map[string]logical.Factory{
"pki": Factory,
},
}
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
NumCores: 1,
HandlerFunc: vaulthttp.Handler,
})
cluster.Start()
defer cluster.Cleanup()
singleCore := cluster.Cores[0]
vault.TestWaitActive(t, singleCore.Core)
client := singleCore.Client

mountPKIEndpoint(t, client, "pki")

// Attempt multiple urls
crls := []string{
"ldap://ldap.example.com/cn=example%20CA,dc=example,dc=com?certificateRevocationList;binary",
"ldap://ldap.example.com/cn=CA,dc=example,dc=com?authorityRevocationList;binary",
}

_, err := client.Logical().Write("pki/config/urls", map[string]interface{}{
"crl_distribution_points": crls,
})
require.NoError(t, err)

resp, err := client.Logical().Read("pki/config/urls")
require.NoError(t, err, "failed reading config/urls")
require.NotNil(t, resp, "resp was nil")
require.NotNil(t, resp.Data, "data within response was nil")
require.NotEmpty(t, resp.Data["crl_distribution_points"], "crl_distribution_points was nil within data")
require.Len(t, resp.Data["crl_distribution_points"], len(crls))

for _, crlVal := range crls {
require.Contains(t, resp.Data["crl_distribution_points"], crlVal)
}

resp, err = client.Logical().Write("pki/root/generate/internal", map[string]interface{}{
"ttl": "40h",
"common_name": "Root R1",
"key_type": "ec",
})
require.NoError(t, err)
require.NotNil(t, resp)
require.NotNil(t, resp.Data)
require.NotEmpty(t, resp.Data["issuer_id"])
rootIssuerId := resp.Data["issuer_id"].(string)

_, err = client.Logical().Write("pki/roles/example-root", map[string]interface{}{
"allowed_domains": "example.com",
"allow_subdomains": "true",
"max_ttl": "1h",
"key_type": "ec",
"issuer_ref": rootIssuerId,
})
require.NoError(t, err)

resp, err = client.Logical().Write("pki/issue/example-root", map[string]interface{}{
"common_name": "test.example.com",
"ttl": "5m",
})
require.NoError(t, err)
require.NotNil(t, resp)
require.NotNil(t, resp.Data)
require.NotEmpty(t, resp.Data["certificate"])

certPEM := resp.Data["certificate"].(string)
certBlock, _ := pem.Decode([]byte(certPEM))
require.NotNil(t, certBlock)
cert, err := x509.ParseCertificate(certBlock.Bytes)
require.NoError(t, err)

require.EqualValues(t, crls, cert.CRLDistributionPoints)
}

func TestIntegrationOCSPClientWithPKI(t *testing.T) {
t.Parallel()

Expand Down
34 changes: 32 additions & 2 deletions builtin/logical/pki/issuing/aia.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ package issuing
import (
"context"
"fmt"
"net/url"
"strings"
"unicode/utf8"

"github.com/asaskevich/govalidator"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/logical"
)
Expand Down Expand Up @@ -145,10 +146,39 @@ func GetClusterConfig(ctx context.Context, s logical.Storage) (*ClusterConfigEnt

func ValidateURLs(urls []string) string {
for _, curr := range urls {
if !govalidator.IsURL(curr) || strings.Contains(curr, "{{issuer_id}}") || strings.Contains(curr, "{{cluster_path}}") || strings.Contains(curr, "{{cluster_aia_path}}") {
if !isURL(curr) || strings.Contains(curr, "{{issuer_id}}") || strings.Contains(curr, "{{cluster_path}}") || strings.Contains(curr, "{{cluster_aia_path}}") {
return curr
}
}

return ""
}

const (
maxURLRuneCount = 2083
minURLRuneCount = 3
)

// IsURL checks if the string is an URL.
func isURL(str string) bool {
if str == "" || utf8.RuneCountInString(str) >= maxURLRuneCount || len(str) <= minURLRuneCount || strings.HasPrefix(str, ".") {
return false
}
strTemp := str
if strings.Contains(str, ":") && !strings.Contains(str, "://") {
// support no indicated urlscheme but with colon for port number
// http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString
strTemp = "http://" + str
}
u, err := url.ParseRequestURI(strTemp)
if err != nil {
return false
}
if strings.HasPrefix(u.Host, ".") {
return false
}
if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
return false
}
return true
}
3 changes: 3 additions & 0 deletions changelog/26477.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
secrets/pki: fixed validation bug which rejected ldap schemed URLs in crl_distribution_points.
```

0 comments on commit 8645e74

Please sign in to comment.