Add a helper function to build ACME API patterns (#20180)

- Add a helper function that can accept the final API path along with
   the pattern function for an ACME api definition and generate the
   various flavors for the given API
This commit is contained in:
Steven Clark
2023-04-14 14:48:33 -04:00
committed by GitHub
parent 3e022a3910
commit 3acbeddf7a
8 changed files with 57 additions and 191 deletions

View File

@@ -153,6 +153,27 @@ func (b *backend) acmeAccountRequiredWrapper(op acmeAccountRequiredOperation) fr
}) })
} }
// A helper function that will build up the various path patterns we want for ACME APIs.
func buildAcmeFrameworkPaths(b *backend, patternFunc func(b *backend, pattern string) *framework.Path, acmeApi string) []*framework.Path {
var patterns []*framework.Path
for _, baseUrl := range []string{
"acme",
"roles/" + framework.GenericNameRegex("role") + "/acme",
"issuer/" + framework.GenericNameRegex(issuerRefParam) + "/acme",
"issuer/" + framework.GenericNameRegex(issuerRefParam) + "/roles/" + framework.GenericNameRegex("role") + "/acme",
} {
if !strings.HasPrefix(acmeApi, "/") {
acmeApi = "/" + acmeApi
}
path := patternFunc(b, baseUrl+acmeApi)
patterns = append(patterns, path)
}
return patterns
}
func getAcmeBaseUrl(sc *storageContext, path string) (*url.URL, error) { func getAcmeBaseUrl(sc *storageContext, path string) (*url.URL, error) {
cfg, err := sc.getClusterConfig() cfg, err := sc.getClusterConfig()
if err != nil { if err != nil {

View File

@@ -216,43 +216,7 @@ func Backend(conf *logical.BackendConfig) *backend {
pathResignCrls(&b), pathResignCrls(&b),
pathSignRevocationList(&b), pathSignRevocationList(&b),
// ACME APIs // ACME APIs see below
pathAcmeRootDirectory(&b),
pathAcmeRoleDirectory(&b),
pathAcmeIssuerDirectory(&b),
pathAcmeIssuerAndRoleDirectory(&b),
pathAcmeRootNonce(&b),
pathAcmeRoleNonce(&b),
pathAcmeIssuerNonce(&b),
pathAcmeIssuerAndRoleNonce(&b),
pathAcmeRootNewAccount(&b),
pathAcmeRoleNewAccount(&b),
pathAcmeIssuerNewAccount(&b),
pathAcmeIssuerAndRoleNewAccount(&b),
pathAcmeRootUpdateAccount(&b),
pathAcmeRoleUpdateAccount(&b),
pathAcmeIssuerUpdateAccount(&b),
pathAcmeIssuerAndRoleUpdateAccount(&b),
pathAcmeRootAuthorization(&b),
pathAcmeRoleAuthorization(&b),
pathAcmeIssuerAuthorization(&b),
pathAcmeIssuerAndRoleAuthorization(&b),
pathAcmeRootChallenge(&b),
pathAcmeRoleChallenge(&b),
pathAcmeIssuerChallenge(&b),
pathAcmeIssuerAndRoleChallenge(&b),
pathAcmeRootNewOrder(&b),
pathAcmeRoleNewOrder(&b),
pathAcmeIssuerNewOrder(&b),
pathAcmeIssuerAndRoleNewOrder(&b),
pathAcmeRootListOrders(&b),
pathAcmeRoleListOrders(&b),
pathAcmeIssuerListOrders(&b),
pathAcmeIssuerAndRoleListOrders(&b),
pathAcmeRootGetOrder(&b),
pathAcmeRoleGetOrder(&b),
pathAcmeIssuerGetOrder(&b),
pathAcmeIssuerAndRoleGetOrder(&b),
}, },
Secrets: []*framework.Secret{ Secrets: []*framework.Secret{
@@ -265,6 +229,22 @@ func Backend(conf *logical.BackendConfig) *backend {
PeriodicFunc: b.periodicFunc, PeriodicFunc: b.periodicFunc,
} }
// Add ACME paths to backend
var acmePaths []*framework.Path
acmePaths = append(acmePaths, pathAcmeDirectory(&b)...)
acmePaths = append(acmePaths, pathAcmeNonce(&b)...)
acmePaths = append(acmePaths, pathAcmeNewAccount(&b)...)
acmePaths = append(acmePaths, pathAcmeUpdateAccount(&b)...)
acmePaths = append(acmePaths, pathAcmeGetOrder(&b)...)
acmePaths = append(acmePaths, pathAcmeListOrders(&b)...)
acmePaths = append(acmePaths, pathAcmeNewOrder(&b)...)
acmePaths = append(acmePaths, pathAcmeChallenge(&b)...)
acmePaths = append(acmePaths, pathAcmeAuthorization(&b)...)
for _, acmePath := range acmePaths {
b.Backend.Paths = append(b.Backend.Paths, acmePath)
}
// Add specific un-auth'd paths for ACME APIs // Add specific un-auth'd paths for ACME APIs
for _, acmePrefix := range []string{"", "issuer/+/", "roles/+/", "issuer/+/roles/+/"} { for _, acmePrefix := range []string{"", "issuer/+/", "roles/+/", "issuer/+/roles/+/"} {
b.PathsSpecial.Unauthenticated = append(b.PathsSpecial.Unauthenticated, acmePrefix+"acme/directory") b.PathsSpecial.Unauthenticated = append(b.PathsSpecial.Unauthenticated, acmePrefix+"acme/directory")

View File

@@ -10,22 +10,8 @@ import (
"github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/logical"
) )
func pathAcmeRootAuthorization(b *backend) *framework.Path { func pathAcmeAuthorization(b *backend) []*framework.Path {
return patternAcmeAuthorization(b, "acme/authorization/"+framework.MatchAllRegex("auth_id")) return buildAcmeFrameworkPaths(b, patternAcmeAuthorization, "/authorization/"+framework.MatchAllRegex("auth_id"))
}
func pathAcmeRoleAuthorization(b *backend) *framework.Path {
return patternAcmeAuthorization(b, "roles/"+framework.GenericNameRegex("role")+"/acme/authorization/"+framework.MatchAllRegex("auth_id"))
}
func pathAcmeIssuerAuthorization(b *backend) *framework.Path {
return patternAcmeAuthorization(b, "issuer/"+framework.GenericNameRegex(issuerRefParam)+"/acme/authorization/"+framework.MatchAllRegex("auth_id"))
}
func pathAcmeIssuerAndRoleAuthorization(b *backend) *framework.Path {
return patternAcmeAuthorization(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+
"/roles/"+framework.GenericNameRegex("role")+"/acme/authorization/"+framework.MatchAllRegex("auth_id"))
} }
func addFieldsForACMEAuthorization(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema { func addFieldsForACMEAuthorization(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema {

View File

@@ -10,32 +10,9 @@ import (
"github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/logical"
) )
func pathAcmeRootChallenge(b *backend) *framework.Path { func pathAcmeChallenge(b *backend) []*framework.Path {
return patternAcmeChallenge(b, return buildAcmeFrameworkPaths(b, patternAcmeChallenge,
"acme/challenge/"+framework.MatchAllRegex("auth_id")+"/"+ "/challenge/"+framework.MatchAllRegex("auth_id")+"/"+framework.MatchAllRegex("challenge_type"))
framework.MatchAllRegex("challenge_type"))
}
func pathAcmeRoleChallenge(b *backend) *framework.Path {
return patternAcmeChallenge(b,
"roles/"+framework.GenericNameRegex("role")+"/acme/challenge/"+
framework.MatchAllRegex("auth_id")+"/"+
framework.MatchAllRegex("challenge_type"))
}
func pathAcmeIssuerChallenge(b *backend) *framework.Path {
return patternAcmeChallenge(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+"/acme/challenge/"+
framework.MatchAllRegex("auth_id")+"/"+
framework.MatchAllRegex("challenge_type"))
}
func pathAcmeIssuerAndRoleChallenge(b *backend) *framework.Path {
return patternAcmeChallenge(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+
"/roles/"+framework.GenericNameRegex("role")+"/acme/challenge/"+
framework.MatchAllRegex("auth_id")+"/"+
framework.MatchAllRegex("challenge_type"))
} }
func addFieldsForACMEChallenge(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema { func addFieldsForACMEChallenge(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema {

View File

@@ -17,22 +17,8 @@ const (
pathAcmeDirectoryHelpDesc = `Provide an ACME directory response that contains URLS for various ACME operations.` pathAcmeDirectoryHelpDesc = `Provide an ACME directory response that contains URLS for various ACME operations.`
) )
func pathAcmeRootDirectory(b *backend) *framework.Path { func pathAcmeDirectory(b *backend) []*framework.Path {
return patternAcmeDirectory(b, "acme/directory") return buildAcmeFrameworkPaths(b, patternAcmeDirectory, "/directory")
}
func pathAcmeRoleDirectory(b *backend) *framework.Path {
return patternAcmeDirectory(b, "roles/"+framework.GenericNameRegex("role")+"/acme/directory")
}
func pathAcmeIssuerDirectory(b *backend) *framework.Path {
return patternAcmeDirectory(b, "issuer/"+framework.GenericNameRegex(issuerRefParam)+"/acme/directory")
}
func pathAcmeIssuerAndRoleDirectory(b *backend) *framework.Path {
return patternAcmeDirectory(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+
"/roles/"+framework.GenericNameRegex("role")+"/acme/directory")
} }
func patternAcmeDirectory(b *backend, pattern string) *framework.Path { func patternAcmeDirectory(b *backend, pattern string) *framework.Path {

View File

@@ -18,40 +18,12 @@ func uuidNameRegex(name string) string {
return fmt.Sprintf("(?P<%s>[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}?)", name) return fmt.Sprintf("(?P<%s>[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}?)", name)
} }
func pathAcmeRootNewAccount(b *backend) *framework.Path { func pathAcmeNewAccount(b *backend) []*framework.Path {
return patternAcmeNewAccount(b, "acme/new-account") return buildAcmeFrameworkPaths(b, patternAcmeNewAccount, "/new-account")
} }
func pathAcmeRoleNewAccount(b *backend) *framework.Path { func pathAcmeUpdateAccount(b *backend) []*framework.Path {
return patternAcmeNewAccount(b, "roles/"+framework.GenericNameRegex("role")+"/acme/new-account") return buildAcmeFrameworkPaths(b, patternAcmeNewAccount, "/account/"+uuidNameRegex("kid"))
}
func pathAcmeIssuerNewAccount(b *backend) *framework.Path {
return patternAcmeNewAccount(b, "issuer/"+framework.GenericNameRegex(issuerRefParam)+"/acme/new-account")
}
func pathAcmeIssuerAndRoleNewAccount(b *backend) *framework.Path {
return patternAcmeNewAccount(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+
"/roles/"+framework.GenericNameRegex("role")+"/acme/new-account")
}
func pathAcmeRootUpdateAccount(b *backend) *framework.Path {
return patternAcmeNewAccount(b, "acme/account/"+uuidNameRegex("kid"))
}
func pathAcmeRoleUpdateAccount(b *backend) *framework.Path {
return patternAcmeNewAccount(b, "roles/"+framework.GenericNameRegex("role")+"/acme/account/"+uuidNameRegex("kid"))
}
func pathAcmeIssuerUpdateAccount(b *backend) *framework.Path {
return patternAcmeNewAccount(b, "issuer/"+framework.GenericNameRegex(issuerRefParam)+"/acme/account/"+uuidNameRegex("kid"))
}
func pathAcmeIssuerAndRoleUpdateAccount(b *backend) *framework.Path {
return patternAcmeNewAccount(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+
"/roles/"+framework.GenericNameRegex("role")+"/acme/account/"+uuidNameRegex("kid"))
} }
func addFieldsForACMEPath(fields map[string]*framework.FieldSchema, pattern string) map[string]*framework.FieldSchema { func addFieldsForACMEPath(fields map[string]*framework.FieldSchema, pattern string) map[string]*framework.FieldSchema {

View File

@@ -11,22 +11,8 @@ import (
"github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/logical"
) )
func pathAcmeRootNonce(b *backend) *framework.Path { func pathAcmeNonce(b *backend) []*framework.Path {
return patternAcmeNonce(b, "acme/new-nonce") return buildAcmeFrameworkPaths(b, patternAcmeNonce, "/new-nonce")
}
func pathAcmeRoleNonce(b *backend) *framework.Path {
return patternAcmeNonce(b, "roles/"+framework.GenericNameRegex("role")+"/acme/new-nonce")
}
func pathAcmeIssuerNonce(b *backend) *framework.Path {
return patternAcmeNonce(b, "issuer/"+framework.GenericNameRegex(issuerRefParam)+"/acme/new-nonce")
}
func pathAcmeIssuerAndRoleNonce(b *backend) *framework.Path {
return patternAcmeNonce(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+
"/roles/"+framework.GenericNameRegex("role")+"/acme/new-nonce")
} }
func patternAcmeNonce(b *backend, pattern string) *framework.Path { func patternAcmeNonce(b *backend, pattern string) *framework.Path {

View File

@@ -14,58 +14,16 @@ import (
"golang.org/x/net/idna" "golang.org/x/net/idna"
) )
func pathAcmeRootListOrders(b *backend) *framework.Path { func pathAcmeListOrders(b *backend) []*framework.Path {
return patternAcmeListOrders(b, "acme/orders") return buildAcmeFrameworkPaths(b, patternAcmeListOrders, "/orders")
} }
func pathAcmeRoleListOrders(b *backend) *framework.Path { func pathAcmeGetOrder(b *backend) []*framework.Path {
return patternAcmeListOrders(b, "roles/"+framework.GenericNameRegex("role")+"/acme/orders") return buildAcmeFrameworkPaths(b, patternAcmeGetOrder, "/order/"+uuidNameRegex("order_id"))
} }
func pathAcmeIssuerListOrders(b *backend) *framework.Path { func pathAcmeNewOrder(b *backend) []*framework.Path {
return patternAcmeListOrders(b, "issuer/"+framework.GenericNameRegex(issuerRefParam)+"/acme/orders") return buildAcmeFrameworkPaths(b, patternAcmeNewOrder, "/new-order")
}
func pathAcmeIssuerAndRoleListOrders(b *backend) *framework.Path {
return patternAcmeListOrders(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+
"/roles/"+framework.GenericNameRegex("role")+"/acme/orders")
}
func pathAcmeRootGetOrder(b *backend) *framework.Path {
return patternAcmeGetOrder(b, "acme/order/"+uuidNameRegex("order_id"))
}
func pathAcmeRoleGetOrder(b *backend) *framework.Path {
return patternAcmeGetOrder(b, "roles/"+framework.GenericNameRegex("role")+"/acme/order/"+uuidNameRegex("order_id"))
}
func pathAcmeIssuerGetOrder(b *backend) *framework.Path {
return patternAcmeGetOrder(b, "issuer/"+framework.GenericNameRegex(issuerRefParam)+"/acme/order/"+uuidNameRegex("order_id"))
}
func pathAcmeIssuerAndRoleGetOrder(b *backend) *framework.Path {
return patternAcmeGetOrder(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+
"/roles/"+framework.GenericNameRegex("role")+"/acme/order/"+uuidNameRegex("order_id"))
}
func pathAcmeRootNewOrder(b *backend) *framework.Path {
return patternAcmeNewOrder(b, "acme/new-order")
}
func pathAcmeRoleNewOrder(b *backend) *framework.Path {
return patternAcmeNewOrder(b, "roles/"+framework.GenericNameRegex("role")+"/acme/new-order")
}
func pathAcmeIssuerNewOrder(b *backend) *framework.Path {
return patternAcmeNewOrder(b, "issuer/"+framework.GenericNameRegex(issuerRefParam)+"/acme/new-order")
}
func pathAcmeIssuerAndRoleNewOrder(b *backend) *framework.Path {
return patternAcmeNewOrder(b,
"issuer/"+framework.GenericNameRegex(issuerRefParam)+
"/roles/"+framework.GenericNameRegex("role")+"/acme/new-order")
} }
func patternAcmeNewOrder(b *backend, pattern string) *framework.Path { func patternAcmeNewOrder(b *backend, pattern string) *framework.Path {