| 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"` |
| } |