fix: o on an Azure secret opens its page in the portal
Not the vault's list of secrets: the secret's own page (asset/ Microsoft_Azure_KeyVault/Secret/<id>), and in the versions view, the version's (<id>/<version>), keys' and certificates' versions too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
3 files changed
+30
-6
No files matched your search
@@ -299,7 +299,7 @@ func (p *Provider) Objects(ctx context.Context, c provider.Container, t provider
|
|||||||
if s.ID == nil || deref(s.Managed) {
|
if s.ID == nil || deref(s.Managed) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
out = append(out, secretObject(c, s))
|
out = append(out, secretObject(c, s, p.tenant(c.Source.ID)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case provider.TypeKey:
|
case provider.TypeKey:
|
||||||
@@ -392,7 +392,7 @@ func (p *Provider) Versions(ctx context.Context, o provider.Object) ([]provider.
|
|||||||
}
|
}
|
||||||
for _, s := range page.Value {
|
for _, s := range page.Value {
|
||||||
if s.ID != nil {
|
if s.ID != nil {
|
||||||
out = append(out, secretObject(o.Container, s))
|
out = append(out, secretObject(o.Container, s, p.tenant(o.Container.Source.ID)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,8 +425,13 @@ func (p *Provider) Versions(ctx context.Context, o provider.Object) ([]provider.
|
|||||||
default:
|
default:
|
||||||
return nil, provider.ErrUnsupported
|
return nil, provider.ErrUnsupported
|
||||||
}
|
}
|
||||||
|
tenant := p.tenant(o.Container.Source.ID)
|
||||||
for i := range out {
|
for i := range out {
|
||||||
out[i].Reference = versionedReference(out[i])
|
out[i].Reference = versionedReference(out[i])
|
||||||
|
if o.Type != provider.TypeSecret { // secretObject's is the version's already
|
||||||
|
kind := map[provider.ObjectType]string{provider.TypeKey: "Key", provider.TypeCertificate: "Certificate"}[o.Type]
|
||||||
|
out[i].URL = portalAssetURL(tenant, kind, out[i].ID+"/"+out[i].Version) // the version's page
|
||||||
|
}
|
||||||
}
|
}
|
||||||
slices.SortFunc(out, func(a, b provider.Object) int { return b.Updated.Compare(a.Updated) })
|
slices.SortFunc(out, func(a, b provider.Object) int { return b.Updated.Compare(a.Updated) })
|
||||||
return out, nil
|
return out, nil
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import (
|
|||||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys"
|
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys"
|
||||||
|
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets"
|
||||||
|
|
||||||
"git.kebcloud.no/keb/lazysecrets/internal/provider"
|
"git.kebcloud.no/keb/lazysecrets/internal/provider"
|
||||||
)
|
)
|
||||||
@@ -334,6 +335,21 @@ func TestPortalURLs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSecretPages(t *testing.T) {
|
||||||
|
c := provider.Container{Detail: "https://kv-app.vault.azure.net/"}
|
||||||
|
base := "https://portal.azure.com/#@contoso.onmicrosoft.com/asset/Microsoft_Azure_KeyVault/Secret/https://kv-app.vault.azure.net/secrets/db"
|
||||||
|
for id, want := range map[string]string{
|
||||||
|
"https://kv-app.vault.azure.net/secrets/db": base, // listed: the secret's page
|
||||||
|
"https://kv-app.vault.azure.net/secrets/db/06140fa2b9a64869a96ef040f6d4dcab": base + "/06140fa2b9a64869a96ef040f6d4dcab", // a version's
|
||||||
|
} {
|
||||||
|
sid := azsecrets.ID(id)
|
||||||
|
o := secretObject(c, &azsecrets.SecretProperties{ID: &sid}, "contoso.onmicrosoft.com")
|
||||||
|
if o.URL != want {
|
||||||
|
t.Errorf("%s: %q, want %q", id, o.URL, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestVersionedReference(t *testing.T) {
|
func TestVersionedReference(t *testing.T) {
|
||||||
sec := provider.Object{Type: provider.TypeSecret, Version: "v1",
|
sec := provider.Object{Type: provider.TypeSecret, Version: "v1",
|
||||||
Reference: "@Microsoft.KeyVault(SecretUri=https://kv.vault.azure.net/secrets/s)"}
|
Reference: "@Microsoft.KeyVault(SecretUri=https://kv.vault.azure.net/secrets/s)"}
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ func PortalResourceURL(tenant, resourceID, blade string) string {
|
|||||||
return portal + tenantPrefix(tenant) + "resource" + resourceID + "/" + blade
|
return portal + tenantPrefix(tenant) + "resource" + resourceID + "/" + blade
|
||||||
}
|
}
|
||||||
|
|
||||||
// portalAssetURL links to a Key Vault object's page; objectID must include
|
// portalAssetURL links to a Key Vault object's page: a version's with
|
||||||
// the version.
|
// one in objectID; a secret's own (its versions) without.
|
||||||
func portalAssetURL(tenant, kind, objectID string) string {
|
func portalAssetURL(tenant, kind, objectID string) string {
|
||||||
return portal + tenantPrefix(tenant) + "asset/Microsoft_Azure_KeyVault/" + kind + "/" + objectID
|
return portal + tenantPrefix(tenant) + "asset/Microsoft_Azure_KeyVault/" + kind + "/" + objectID
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,10 @@ func objectURL(c provider.Container, collection, name string) string {
|
|||||||
return strings.TrimSuffix(c.Detail, "/") + "/" + collection + "/" + name
|
return strings.TrimSuffix(c.Detail, "/") + "/" + collection + "/" + name
|
||||||
}
|
}
|
||||||
|
|
||||||
func secretObject(c provider.Container, p *azsecrets.SecretProperties) provider.Object {
|
// secretObject is a secret, or a version of one, from a listing. Its URL
|
||||||
|
// is its page in the portal: the secret's (with its versions), or with
|
||||||
|
// a version, that version's.
|
||||||
|
func secretObject(c provider.Container, p *azsecrets.SecretProperties, tenant string) provider.Object {
|
||||||
name := p.ID.Name()
|
name := p.ID.Name()
|
||||||
url := objectURL(c, "secrets", name)
|
url := objectURL(c, "secrets", name)
|
||||||
o := provider.Object{
|
o := provider.Object{
|
||||||
@@ -100,7 +103,7 @@ func secretObject(c provider.Container, p *azsecrets.SecretProperties) provider.
|
|||||||
ContentType: deref(p.ContentType),
|
ContentType: deref(p.ContentType),
|
||||||
Tags: tags(p.Tags),
|
Tags: tags(p.Tags),
|
||||||
Reference: "@Microsoft.KeyVault(SecretUri=" + url + ")",
|
Reference: "@Microsoft.KeyVault(SecretUri=" + url + ")",
|
||||||
URL: ObjectListURL(c, provider.TypeSecret),
|
URL: portalAssetURL(tenant, "Secret", strings.TrimSuffix(url+"/"+p.ID.Version(), "/")),
|
||||||
}
|
}
|
||||||
if a := p.Attributes; a != nil {
|
if a := p.Attributes; a != nil {
|
||||||
o.Enabled, o.Updated, o.Expires = a.Enabled, deref(a.Updated), deref(a.Expires)
|
o.Enabled, o.Updated, o.Expires = a.Enabled, deref(a.Updated), deref(a.Expires)
|
||||||
|
|||||||
Reference in new issue
Block a user