forked from spiffe/spire
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
No longer emit x509UniqueIdentifier in X509-SVIDs
Introduced in 1.4.2, this practice has turned out to be problematic. This change updates SPIRE Server to no long emit attribute in the X509-SVID subject. It also introduces a new built-in CredentialComposer to add the attribute back in for deployments that rely on it. The plugin only augments workload X509-SVIDs. Server and agent X509-SVIDs are not modified. Fixes: spiffe#4755 Fixes: spiffe#3110 Signed-off-by: Andrew Harding <azdagron@gmail.com>
- Loading branch information
Showing
7 changed files
with
246 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Server plugin: CredentialComposer "uniqueid" | ||
|
||
The `uniqueid` plugin adds the `x509UniqueIdentifier` attribute to the X509-SVID subject for workloads. Server and agent X509-SVIDs are not modified. | ||
|
||
The x509UniqueIdentifier is formed from a hash of the SPIFFE ID of the workload. | ||
|
||
This plugin is intended for backwards compatibility for deployments that have come to rely on this attribute (introduced in SPIRE 1.4.2 and reverted in SPIRE 1.9.0). | ||
|
||
This plugin has no configuration. To use the plugin, add it to the plugins section of the SPIRE Server configuration: | ||
|
||
``` | ||
plugins { | ||
CredentialComposer "uniqueid" {} | ||
// ... other plugins ... | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
pkg/server/plugin/credentialcomposer/uniqueid/plugin.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package uniqueid | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/spiffe/go-spiffe/v2/spiffeid" | ||
credentialcomposerv1 "github.com/spiffe/spire-plugin-sdk/proto/spire/plugin/server/credentialcomposer/v1" | ||
"github.com/spiffe/spire/pkg/common/catalog" | ||
"github.com/spiffe/spire/pkg/common/x509svid" | ||
"google.golang.org/grpc/codes" | ||
"google.golang.org/grpc/status" | ||
) | ||
|
||
func BuiltIn() catalog.BuiltIn { | ||
return builtIn(New()) | ||
} | ||
|
||
func builtIn(p *Plugin) catalog.BuiltIn { | ||
return catalog.MakeBuiltIn("uniqueid", | ||
credentialcomposerv1.CredentialComposerPluginServer(p), | ||
) | ||
} | ||
|
||
type Plugin struct { | ||
credentialcomposerv1.UnsafeCredentialComposerServer | ||
} | ||
|
||
func New() *Plugin { | ||
return &Plugin{} | ||
} | ||
|
||
func (p *Plugin) ComposeServerX509CA(context.Context, *credentialcomposerv1.ComposeServerX509CARequest) (*credentialcomposerv1.ComposeServerX509CAResponse, error) { | ||
// Intentionally not implemented. | ||
return nil, status.Error(codes.Unimplemented, "not implemented") | ||
} | ||
|
||
func (p *Plugin) ComposeServerX509SVID(context.Context, *credentialcomposerv1.ComposeServerX509SVIDRequest) (*credentialcomposerv1.ComposeServerX509SVIDResponse, error) { | ||
// Intentionally not implemented. | ||
return nil, status.Error(codes.Unimplemented, "not implemented") | ||
} | ||
|
||
func (p *Plugin) ComposeAgentX509SVID(context.Context, *credentialcomposerv1.ComposeAgentX509SVIDRequest) (*credentialcomposerv1.ComposeAgentX509SVIDResponse, error) { | ||
// Intentionally not implemented. | ||
return nil, status.Error(codes.Unimplemented, "not implemented") | ||
} | ||
|
||
func (p *Plugin) ComposeWorkloadX509SVID(_ context.Context, req *credentialcomposerv1.ComposeWorkloadX509SVIDRequest) (*credentialcomposerv1.ComposeWorkloadX509SVIDResponse, error) { | ||
switch { | ||
case req.Attributes == nil: | ||
return nil, status.Error(codes.InvalidArgument, "request missing attributes") | ||
case req.SpiffeId == "": | ||
return nil, status.Error(codes.InvalidArgument, "request missing SPIFFE ID") | ||
} | ||
|
||
uniqueID, err := uniqueIDAttributeTypeAndValue(req.SpiffeId) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// No need to clone | ||
attributes := req.Attributes | ||
if attributes.Subject == nil { | ||
attributes.Subject = &credentialcomposerv1.DistinguishedName{} | ||
} | ||
|
||
// Add the attribute if does not already exist. Otherwise replace the old value. | ||
found := false | ||
for i := 0; i < len(attributes.Subject.ExtraNames); i++ { | ||
if attributes.Subject.ExtraNames[i].Oid == uniqueID.Oid { | ||
attributes.Subject.ExtraNames[i] = uniqueID | ||
found = true | ||
break | ||
} | ||
} | ||
if !found { | ||
attributes.Subject.ExtraNames = append(attributes.Subject.ExtraNames, uniqueID) | ||
} | ||
|
||
return &credentialcomposerv1.ComposeWorkloadX509SVIDResponse{ | ||
Attributes: attributes, | ||
}, nil | ||
} | ||
|
||
func (p *Plugin) ComposeWorkloadJWTSVID(context.Context, *credentialcomposerv1.ComposeWorkloadJWTSVIDRequest) (*credentialcomposerv1.ComposeWorkloadJWTSVIDResponse, error) { | ||
// Intentionally not implemented. | ||
return nil, status.Error(codes.Unimplemented, "not implemented") | ||
} | ||
|
||
func uniqueIDAttributeTypeAndValue(id string) (*credentialcomposerv1.AttributeTypeAndValue, error) { | ||
spiffeID, err := spiffeid.FromString(id) | ||
if err != nil { | ||
return nil, status.Errorf(codes.InvalidArgument, "malformed SPIFFE ID: %v", err) | ||
} | ||
|
||
uniqueID := x509svid.UniqueIDAttribute(spiffeID) | ||
|
||
oid := uniqueID.Type.String() | ||
stringValue, ok := uniqueID.Value.(string) | ||
if !ok { | ||
// purely defensive. | ||
return nil, status.Errorf(codes.Internal, "unique ID value is not a string") | ||
} | ||
|
||
return &credentialcomposerv1.AttributeTypeAndValue{ | ||
Oid: oid, | ||
StringValue: stringValue, | ||
}, nil | ||
} |
Oops, something went wrong.