shell.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. Copyright © 2022 ESO Maintainer Team
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package shell
  14. import (
  15. "bufio"
  16. "bytes"
  17. "context"
  18. "errors"
  19. "fmt"
  20. "io"
  21. "net"
  22. "os"
  23. "os/signal"
  24. "syscall"
  25. esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
  26. esapi "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  27. pb "github.com/external-secrets/external-secrets/pkg/plugin/grpc"
  28. "github.com/go-logr/logr"
  29. "google.golang.org/grpc"
  30. corev1 "k8s.io/api/core/v1"
  31. "k8s.io/apimachinery/pkg/runtime"
  32. "k8s.io/apimachinery/pkg/runtime/serializer"
  33. "k8s.io/apimachinery/pkg/util/yaml"
  34. clientgoscheme "k8s.io/client-go/kubernetes/scheme"
  35. ctrl "sigs.k8s.io/controller-runtime"
  36. "sigs.k8s.io/controller-runtime/pkg/client"
  37. ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
  38. "sigs.k8s.io/controller-runtime/pkg/client/fake"
  39. ctrllog "sigs.k8s.io/controller-runtime/pkg/log"
  40. "sigs.k8s.io/controller-runtime/pkg/log/zap"
  41. )
  42. type Server struct {
  43. pb.UnimplementedSecretsClientServer
  44. provider esapi.Provider
  45. scheme *runtime.Scheme
  46. log logr.Logger
  47. }
  48. func init() {
  49. ctrllog.SetLogger(zap.New())
  50. }
  51. func RunServer(provider esapi.Provider) error {
  52. log := ctrl.Log.WithName("provider")
  53. providerName, ok := esapi.GetProviderNameByType(provider)
  54. if !ok {
  55. return errors.New("could not get provider name by type")
  56. }
  57. scheme := runtime.NewScheme()
  58. esapi.AddToScheme(scheme)
  59. clientgoscheme.AddToScheme(scheme)
  60. pluginServer := &Server{
  61. provider: provider,
  62. scheme: scheme,
  63. log: log,
  64. }
  65. sockAddr := fmt.Sprintf("/var/run/eso/provider/sockets/%s.sock", providerName)
  66. _ = os.Remove(sockAddr)
  67. lis, err := net.Listen("unix", sockAddr)
  68. if err != nil {
  69. return fmt.Errorf("failed to listen: %v", err)
  70. }
  71. defer lis.Close()
  72. defer os.Remove(sockAddr)
  73. s := grpc.NewServer()
  74. go func() {
  75. c := make(chan os.Signal, 1) // we need to reserve to buffer size 1, so the notifier are not blocked
  76. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  77. <-c
  78. log.Info("stopping grpc server")
  79. s.GracefulStop()
  80. }()
  81. pb.RegisterSecretsClientServer(s, pluginServer)
  82. log.Info("server listening ", "addr", lis.Addr())
  83. if err := s.Serve(lis); err != nil {
  84. log.Error(err, "failed to serve")
  85. return err
  86. }
  87. return nil
  88. }
  89. func (s *Server) GetSecret(ctx context.Context, req *pb.GetSecretRequest) (*pb.GetSecretReply, error) {
  90. store, err := s.decodeStore(req.Store)
  91. if err != nil {
  92. return nil, err
  93. }
  94. kubeClient, err := s.getClient(req.Objects)
  95. if err != nil {
  96. return nil, err
  97. }
  98. s.log.Info("GetSecret() request", "namespace", req.Namespace, "name", store.GetObjectMeta().Name)
  99. secretsClient, err := s.provider.NewClient(ctx, store, kubeClient, req.Namespace)
  100. if err != nil {
  101. return nil, err
  102. }
  103. secret, err := secretsClient.GetSecret(ctx, remoteRef(req.RemoteRef))
  104. s.log.Info("GetSecret() response", "namespace", req.Namespace, "name", store.GetObjectMeta().Name, "secret", secret, "err", err)
  105. if err != nil {
  106. return &pb.GetSecretReply{
  107. Error: err.Error(),
  108. }, nil
  109. }
  110. return &pb.GetSecretReply{
  111. Secret: secret,
  112. }, nil
  113. }
  114. func (s *Server) GetSecretMap(ctx context.Context, req *pb.GetSecretMapRequest) (*pb.GetSecretMapReply, error) {
  115. store, err := s.decodeStore(req.Store)
  116. if err != nil {
  117. return nil, err
  118. }
  119. s.log.Info("GetSecretMap()", "namespace", req.Namespace, "name", store.GetObjectMeta().Name)
  120. kubeClient, err := s.getClient(req.Objects)
  121. if err != nil {
  122. return nil, err
  123. }
  124. secretsClient, err := s.provider.NewClient(ctx, store, kubeClient, req.Namespace)
  125. if err != nil {
  126. return nil, err
  127. }
  128. secret, err := secretsClient.GetSecretMap(ctx, remoteRef(req.RemoteRef))
  129. if err != nil {
  130. return &pb.GetSecretMapReply{
  131. Error: err.Error(),
  132. }, nil
  133. }
  134. return &pb.GetSecretMapReply{
  135. Data: secret,
  136. }, nil
  137. }
  138. func (s *Server) GetAllSecrets(ctx context.Context, req *pb.GetAllSecretsRequest) (*pb.GetAllSecretsReply, error) {
  139. store, err := s.decodeStore(req.Store)
  140. if err != nil {
  141. return nil, err
  142. }
  143. s.log.Info("GetAllSecrets()", "namespace", req.Namespace, "name", store.GetObjectMeta().Name)
  144. kubeClient, err := s.getClient(req.Objects)
  145. if err != nil {
  146. return nil, err
  147. }
  148. secretsClient, err := s.provider.NewClient(ctx, store,
  149. kubeClient, req.Namespace)
  150. if err != nil {
  151. return nil, err
  152. }
  153. secret, err := secretsClient.GetAllSecrets(ctx, externalSecretFind(req.RemoteRef))
  154. if err != nil {
  155. return &pb.GetAllSecretsReply{
  156. Error: err.Error(),
  157. }, nil
  158. }
  159. return &pb.GetAllSecretsReply{
  160. Data: secret,
  161. }, nil
  162. }
  163. func (s *Server) PushSecret(ctx context.Context, req *pb.PushSecretRequest) (*pb.PushSecretReply, error) {
  164. store, err := s.decodeStore(req.Store)
  165. if err != nil {
  166. return nil, err
  167. }
  168. s.log.Info("PushSecret()", "namespace", req.Namespace, "name", store.GetObjectMeta().Name)
  169. kubeClient, err := s.getClient(req.Objects)
  170. if err != nil {
  171. return nil, err
  172. }
  173. secretsClient, err := s.provider.NewClient(ctx, store, kubeClient, req.Namespace)
  174. if err != nil {
  175. return nil, err
  176. }
  177. err = secretsClient.PushSecret(ctx, req.Secret, pushRemoteRef(req.RemoteRef))
  178. if err != nil {
  179. return &pb.PushSecretReply{
  180. Error: err.Error(),
  181. }, nil
  182. }
  183. return &pb.PushSecretReply{}, nil
  184. }
  185. func (s *Server) DeleteSecret(ctx context.Context, req *pb.DeleteSecretRequest) (*pb.DeleteSecretReply, error) {
  186. store, err := s.decodeStore(req.Store)
  187. if err != nil {
  188. return nil, err
  189. }
  190. s.log.Info("DeleteSecret()", "namespace", req.Namespace, "name", store.GetObjectMeta().Name)
  191. kubeClient, err := s.getClient(req.Objects)
  192. if err != nil {
  193. return nil, err
  194. }
  195. secretsClient, err := s.provider.NewClient(ctx, store, kubeClient, req.Namespace)
  196. if err != nil {
  197. return nil, err
  198. }
  199. err = secretsClient.DeleteSecret(ctx, pushRemoteRef(req.RemoteRef))
  200. if err != nil {
  201. return &pb.DeleteSecretReply{
  202. Error: err.Error(),
  203. }, nil
  204. }
  205. return &pb.DeleteSecretReply{}, nil
  206. }
  207. func externalSecretFind(ref *pb.ExternalSecretFind) esapi.ExternalSecretFind {
  208. find := esapi.ExternalSecretFind{
  209. Tags: ref.Tags,
  210. ConversionStrategy: esapi.ExternalSecretConversionStrategy(ref.ConversionStrategy),
  211. DecodingStrategy: esapi.ExternalSecretDecodingStrategy(ref.GetDecodingStrategy()),
  212. }
  213. if ref.Path != "" {
  214. find.Path = &ref.Path
  215. }
  216. if ref.FindNameRegexp != "" {
  217. find.Name = &esapi.FindName{
  218. RegExp: ref.FindNameRegexp,
  219. }
  220. }
  221. return find
  222. }
  223. func pushRemoteRef(ref *pb.PushRemoteRef) esapi.PushRemoteRef {
  224. return esv1alpha1.PushSecretRemoteRef{
  225. RemoteKey: ref.RemoteKey,
  226. Property: ref.Property,
  227. }
  228. }
  229. func remoteRef(ref *pb.RemoteRef) esapi.ExternalSecretDataRemoteRef {
  230. return esapi.ExternalSecretDataRemoteRef{
  231. Key: ref.Key,
  232. MetadataPolicy: esapi.ExternalSecretMetadataPolicy(ref.MetadataPolicy),
  233. Property: ref.Property,
  234. Version: ref.Version,
  235. ConversionStrategy: esapi.ExternalSecretConversionStrategy(ref.ConversionStrategy),
  236. DecodingStrategy: esapi.ExternalSecretDecodingStrategy(ref.DecodingStrategy),
  237. }
  238. }
  239. func (s *Server) decodeStore(data []byte) (esapi.GenericStore, error) {
  240. obj, gvk, err := serializer.NewCodecFactory(s.scheme).UniversalDeserializer().Decode(data, nil, nil)
  241. if err != nil {
  242. return nil, fmt.Errorf("unable to decode store data: %w", err)
  243. }
  244. switch gvk.Kind {
  245. case esapi.SecretStoreKind:
  246. ss, ok := obj.(*esapi.SecretStore)
  247. if !ok {
  248. return nil, fmt.Errorf("unable to convert SecretStore object")
  249. }
  250. return ss, nil
  251. case esapi.ClusterSecretStoreKind:
  252. css, ok := obj.(*esapi.ClusterSecretStore)
  253. if !ok {
  254. return nil, fmt.Errorf("unable to convert SecretStore object")
  255. }
  256. return css, nil
  257. }
  258. return nil, errors.New("unexpected store data")
  259. }
  260. func (s *Server) decodeObjects(data []byte) ([]client.Object, error) {
  261. s.log.Info("decoded data", "data", data)
  262. decode := serializer.NewCodecFactory(s.scheme).UniversalDeserializer().Decode
  263. reader := yaml.NewYAMLReader(bufio.NewReader(bytes.NewReader(data)))
  264. var objects []client.Object
  265. for {
  266. buf, err := reader.Read()
  267. if err != nil {
  268. if err == io.EOF {
  269. s.log.Error(err, "found EOF")
  270. break
  271. }
  272. s.log.Error(err, "unable to read buf")
  273. return nil, err
  274. }
  275. s.log.Error(err, "decoding buf", "buf", buf)
  276. obj, gvk, err := decode(buf, nil, nil)
  277. if err != nil {
  278. return nil, err
  279. }
  280. s.log.Info("decoded object", "object", obj)
  281. switch item := obj.(type) {
  282. case *corev1.Secret:
  283. objects = append(objects, item)
  284. case *corev1.ConfigMap:
  285. objects = append(objects, item)
  286. default:
  287. return nil, fmt.Errorf("unexpected object type: %s", gvk)
  288. }
  289. }
  290. return objects, nil
  291. }
  292. func (s *Server) getClient(data []byte) (client.Client, error) {
  293. objects, err := s.decodeObjects(data)
  294. if err != nil {
  295. return nil, err
  296. }
  297. restCfg, err := ctrlcfg.GetConfig()
  298. if err != nil {
  299. return nil, err
  300. }
  301. // TODO: do not log secrets
  302. s.log.Info("creating client with cached objects", "objects", objects)
  303. kubeClient, err := client.New(restCfg, client.Options{
  304. Cache: &client.CacheOptions{
  305. Reader: fake.NewClientBuilder().WithScheme(s.scheme).WithObjects(objects...).Build(),
  306. },
  307. Scheme: s.scheme,
  308. })
  309. if err != nil {
  310. return nil, err
  311. }
  312. return kubeClient, nil
  313. }