blob: 2e7bc392b60a7fa466723d08d57011713c866aaa [file]
package drivers
import (
"fmt"
"github.com/docker/docker/pkg/plugingetter"
"github.com/docker/swarmkit/api"
)
const (
// SecretsProviderAPI is the endpoint for fetching secrets from plugins
SecretsProviderAPI = "/SecretProvider.GetSecret"
// SecretsProviderCapability is the secrets provider plugin capability identification
SecretsProviderCapability = "secretprovider"
)
// SecretDriver provides secrets from different stores
type SecretDriver struct {
plugin plugingetter.CompatPlugin
}
// NewSecretDriver creates a new driver that provides third party secrets
func NewSecretDriver(plugin plugingetter.CompatPlugin) *SecretDriver {
return &SecretDriver{plugin: plugin}
}
// Get gets a secret from the secret provider
func (d *SecretDriver) Get(spec *api.SecretSpec, task *api.Task) ([]byte, error) {
if spec == nil {
return nil, fmt.Errorf("secret spec is nil")
}
if task == nil {
return nil, fmt.Errorf("task is nil")
}
var secretResp SecretsProviderResponse
secretReq := &SecretsProviderRequest{
SecretName: spec.Annotations.Name,
ServiceName: task.ServiceAnnotations.Name,
ServiceLabels: task.ServiceAnnotations.Labels,
}
container := task.Spec.GetContainer()
if container != nil {
secretReq.ServiceHostname = container.Hostname
}
if task.Endpoint != nil && task.Endpoint.Spec != nil {
secretReq.ServiceEndpointSpec = &EndpointSpec{
Mode: int32(task.Endpoint.Spec.Mode),
}
for _, p := range task.Endpoint.Spec.Ports {
if p == nil {
continue
}
secretReq.ServiceEndpointSpec.Ports =
append(secretReq.ServiceEndpointSpec.Ports,
PortConfig{
Name: p.Name,
Protocol: int32(p.Protocol),
PublishedPort: p.PublishedPort,
TargetPort: p.TargetPort,
PublishMode: int32(p.PublishMode),
})
}
}
err := d.plugin.Client().Call(SecretsProviderAPI, secretReq, &secretResp)
if err != nil {
return nil, err
}
if secretResp.Err != "" {
return nil, fmt.Errorf(secretResp.Err)
}
// Assign the secret value
return secretResp.Value, nil
}
// SecretsProviderRequest is the secrets provider request.
type SecretsProviderRequest struct {
SecretName string `json:",omitempty"` // SecretName is the name of the secret to request from the plugin
ServiceHostname string `json:",omitempty"` // ServiceHostname is the hostname of the service, can be used for x509 certificate
ServiceName string `json:",omitempty"` // ServiceName is the name of the service that requested the secret
ServiceLabels map[string]string `json:",omitempty"` // ServiceLabels capture environment names and other metadata
ServiceEndpointSpec *EndpointSpec `json:",omitempty"` // ServiceEndpointSpec holds the specification for endpoints
}
// SecretsProviderResponse is the secrets provider response.
type SecretsProviderResponse struct {
Value []byte `json:",omitempty"` // Value is the value of the secret
Err string `json:",omitempty"` // Err is the error response of the plugin
}
// EndpointSpec represents the spec of an endpoint.
type EndpointSpec struct {
Mode int32 `json:",omitempty"`
Ports []PortConfig `json:",omitempty"`
}
// PortConfig represents the config of a port.
type PortConfig struct {
Name string `json:",omitempty"`
Protocol int32 `json:",omitempty"`
// TargetPort is the port inside the container
TargetPort uint32 `json:",omitempty"`
// PublishedPort is the port on the swarm hosts
PublishedPort uint32 `json:",omitempty"`
// PublishMode is the mode in which port is published
PublishMode int32 `json:",omitempty"`
}