secrets.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package drivers
  2. import (
  3. "fmt"
  4. "github.com/docker/docker/pkg/plugingetter"
  5. "github.com/docker/swarmkit/api"
  6. "github.com/docker/swarmkit/api/naming"
  7. )
  8. const (
  9. // SecretsProviderAPI is the endpoint for fetching secrets from plugins
  10. SecretsProviderAPI = "/SecretProvider.GetSecret"
  11. // SecretsProviderCapability is the secrets provider plugin capability identification
  12. SecretsProviderCapability = "secretprovider"
  13. )
  14. // SecretDriver provides secrets from different stores
  15. type SecretDriver struct {
  16. plugin plugingetter.CompatPlugin
  17. }
  18. // NewSecretDriver creates a new driver that provides third party secrets
  19. func NewSecretDriver(plugin plugingetter.CompatPlugin) *SecretDriver {
  20. return &SecretDriver{plugin: plugin}
  21. }
  22. // Get gets a secret from the secret provider. The function returns: the secret value;
  23. // a bool indicating whether the value should be reused across different tasks (defaults to false);
  24. // and an error if either the spec or task are nil, if calling the driver returns an error, or if
  25. // the driver returns an error in the payload.
  26. func (d *SecretDriver) Get(spec *api.SecretSpec, task *api.Task) ([]byte, bool, error) {
  27. if spec == nil {
  28. return nil, false, fmt.Errorf("secret spec is nil")
  29. }
  30. if task == nil {
  31. return nil, false, fmt.Errorf("task is nil")
  32. }
  33. var secretResp SecretsProviderResponse
  34. secretReq := &SecretsProviderRequest{
  35. SecretName: spec.Annotations.Name,
  36. SecretLabels: spec.Annotations.Labels,
  37. ServiceID: task.ServiceID,
  38. ServiceName: task.ServiceAnnotations.Name,
  39. ServiceLabels: task.ServiceAnnotations.Labels,
  40. TaskID: task.ID,
  41. TaskName: naming.Task(task),
  42. TaskImage: task.Spec.GetContainer().Image,
  43. NodeID: task.NodeID,
  44. }
  45. container := task.Spec.GetContainer()
  46. if container != nil {
  47. secretReq.ServiceHostname = container.Hostname
  48. }
  49. if task.Endpoint != nil && task.Endpoint.Spec != nil {
  50. secretReq.ServiceEndpointSpec = &EndpointSpec{
  51. Mode: int32(task.Endpoint.Spec.Mode),
  52. }
  53. for _, p := range task.Endpoint.Spec.Ports {
  54. if p == nil {
  55. continue
  56. }
  57. secretReq.ServiceEndpointSpec.Ports =
  58. append(secretReq.ServiceEndpointSpec.Ports,
  59. PortConfig{
  60. Name: p.Name,
  61. Protocol: int32(p.Protocol),
  62. PublishedPort: p.PublishedPort,
  63. TargetPort: p.TargetPort,
  64. PublishMode: int32(p.PublishMode),
  65. })
  66. }
  67. }
  68. err := d.plugin.Client().Call(SecretsProviderAPI, secretReq, &secretResp)
  69. if err != nil {
  70. return nil, false, err
  71. }
  72. if secretResp.Err != "" {
  73. return nil, secretResp.DoNotReuse, fmt.Errorf(secretResp.Err)
  74. }
  75. // Assign the secret value
  76. return secretResp.Value, secretResp.DoNotReuse, nil
  77. }
  78. // SecretsProviderRequest is the secrets provider request.
  79. type SecretsProviderRequest struct {
  80. SecretName string `json:",omitempty"` // SecretName is the name of the secret to request from the plugin
  81. SecretLabels map[string]string `json:",omitempty"` // SecretLabels capture environment names and other metadata pertaining to the secret
  82. ServiceHostname string `json:",omitempty"` // ServiceHostname is the hostname of the service, can be used for x509 certificate
  83. ServiceID string `json:",omitempty"` // ServiceID is the name of the service that requested the secret
  84. ServiceName string `json:",omitempty"` // ServiceName is the name of the service that requested the secret
  85. ServiceLabels map[string]string `json:",omitempty"` // ServiceLabels capture environment names and other metadata pertaining to the service
  86. TaskID string `json:",omitempty"` // TaskID is the ID of the task that the secret will be assigned to
  87. TaskName string `json:",omitempty"` // TaskName is the name of the task that the secret will be assigned to
  88. TaskImage string `json:",omitempty"` // TaskName is the image of the task that the secret will be assigned to
  89. NodeID string `json:",omitempty"` // NodeID is the ID of the node that the task will be executed on
  90. ServiceEndpointSpec *EndpointSpec `json:",omitempty"` // ServiceEndpointSpec holds the specification for endpoints
  91. }
  92. // SecretsProviderResponse is the secrets provider response.
  93. type SecretsProviderResponse struct {
  94. Value []byte `json:",omitempty"` // Value is the value of the secret
  95. Err string `json:",omitempty"` // Err is the error response of the plugin
  96. // DoNotReuse indicates that the secret returned from this request should
  97. // only be used for one task, and any further tasks should call the secret
  98. // driver again.
  99. DoNotReuse bool `json:",omitempty"`
  100. }
  101. // EndpointSpec represents the spec of an endpoint.
  102. type EndpointSpec struct {
  103. Mode int32 `json:",omitempty"`
  104. Ports []PortConfig `json:",omitempty"`
  105. }
  106. // PortConfig represents the config of a port.
  107. type PortConfig struct {
  108. Name string `json:",omitempty"`
  109. Protocol int32 `json:",omitempty"`
  110. // TargetPort is the port inside the container
  111. TargetPort uint32 `json:",omitempty"`
  112. // PublishedPort is the port on the swarm hosts
  113. PublishedPort uint32 `json:",omitempty"`
  114. // PublishMode is the mode in which port is published
  115. PublishMode int32 `json:",omitempty"`
  116. }