From 6d235788eb1a2a07401a97d2fd39b1a60f77030d Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Wed, 6 Sep 2023 14:35:52 +0530 Subject: [PATCH 1/2] Remove automated cert renewal With the introduction of APNS auth key (https://github.com/mattermost/mattermost-push-proxy/pull/101), there is no need to renew certs any more. We clean it up. --- cmd/renew_apple_cert/README.md | 32 ---- cmd/renew_apple_cert/convert_cert/config.go | 38 ----- .../convert_cert/config.sample.json | 5 - cmd/renew_apple_cert/convert_cert/main.go | 153 ------------------ .../convert_cert/testdata/config.json | 5 - cmd/renew_apple_cert/create_csr/config.go | 43 ----- .../create_csr/config.sample.json | 10 -- cmd/renew_apple_cert/create_csr/main.go | 118 -------------- cmd/renew_apple_cert/create_csr/main_test.go | 19 --- .../create_csr/testdata/config.json | 10 -- 10 files changed, 433 deletions(-) delete mode 100644 cmd/renew_apple_cert/README.md delete mode 100644 cmd/renew_apple_cert/convert_cert/config.go delete mode 100644 cmd/renew_apple_cert/convert_cert/config.sample.json delete mode 100644 cmd/renew_apple_cert/convert_cert/main.go delete mode 100644 cmd/renew_apple_cert/convert_cert/testdata/config.json delete mode 100644 cmd/renew_apple_cert/create_csr/config.go delete mode 100644 cmd/renew_apple_cert/create_csr/config.sample.json delete mode 100644 cmd/renew_apple_cert/create_csr/main.go delete mode 100644 cmd/renew_apple_cert/create_csr/main_test.go delete mode 100644 cmd/renew_apple_cert/create_csr/testdata/config.json diff --git a/cmd/renew_apple_cert/README.md b/cmd/renew_apple_cert/README.md deleted file mode 100644 index 88f0e33..0000000 --- a/cmd/renew_apple_cert/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Utility for renewal or creation of apple push notification certificate -## Description -Automate steps for certificate creation or renewal for apple push notification service. - -### Rough description of tasks: -1. Create a Certificate Signing Request to upload via apple portal and get it signed -2. Download the certificate and convert it so it becomes usable by [mattermost-push-proxy](https://github.com/mattermost/mattermost-push-proxy) - -### Result: -2 scripts, 2 manual steps: -1. scripted creation of CSR via create_csr/main.go -2. manual upload of generated `certs/csr/*.csr` file -3. manual download of signed `aps.cer` file from apple portal -4. scripted extraction + conversion from `aps.cer` to `certs/converted/*_priv.pem` to be then usable for mattermost-push-proxy - -## Usage -### Prerequisites: -```bash -$ openssl version - OpenSSL 1.1.1f 31 Mar 2020 -``` - -### Steps -1. `$ cd cmd/renew_apple_cert/create_csr` -2. `$ cp config.sample.json config.json` -3. Fill in input information in `config/config.json` -4. `$ go run .` -5. Follow https://developers.mattermost.com/contribute/mobile/push-notifications/ios/ to upload the Certificate Signing Request *.csr generated by the script -6. Download the `aps.cer` from the apple portal and put it in `certs/downloaded/aps.cer`\ -7. `$ cd ../convert_cert` -8. `$ go run .` -9. Use `certs/converted/*_priv.pem` in the push proxy configuration as described [here](https://developers.mattermost.com/contribute/mobile/push-notifications/service/#set-up-mattermost-push-notification-service-to-send-ios-push-notifications) diff --git a/cmd/renew_apple_cert/convert_cert/config.go b/cmd/renew_apple_cert/convert_cert/config.go deleted file mode 100644 index 05ed783..0000000 --- a/cmd/renew_apple_cert/convert_cert/config.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -package main - -import ( - "encoding/json" - "fmt" - "os" - - "github.com/kelseyhightower/envconfig" -) - -type config struct { - App string - CertDir string - AppleGateway string -} - -func parseConfig(path string) (config, error) { - var cfg config - file, err := os.Open(path) - if err != nil { - return cfg, fmt.Errorf("could not open file: %w", err) - } - defer file.Close() - - err = json.NewDecoder(file).Decode(&cfg) - if err != nil { - return cfg, fmt.Errorf("could not decode file: %w", err) - } - - if err = envconfig.Process("convert_cert", &cfg); err != nil { - return cfg, err - } - - return cfg, nil -} diff --git a/cmd/renew_apple_cert/convert_cert/config.sample.json b/cmd/renew_apple_cert/convert_cert/config.sample.json deleted file mode 100644 index 6254f9d..0000000 --- a/cmd/renew_apple_cert/convert_cert/config.sample.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "App": "mattermost", - "CertDir": "../certs", - "AppleGateway": "gateway.push.apple.com:2195" -} \ No newline at end of file diff --git a/cmd/renew_apple_cert/convert_cert/main.go b/cmd/renew_apple_cert/convert_cert/main.go deleted file mode 100644 index f1b2794..0000000 --- a/cmd/renew_apple_cert/convert_cert/main.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -package main - -import ( - "flag" - "fmt" - "log" - "os" - "os/exec" - "path" -) - -const ( - csrSubDir = "csr" - downloadedSubDir = "downloaded" - convertedSubDir = "converted" - - // Important files - apsP12 = "aps.p12" - apsPem = "aps.pem" - apsCer = "aps.cer" -) - -func main() { - var configFile string - flag.StringVar(&configFile, "config", "config/config.json", "Configuration file for convert_cert.") - flag.Parse() - - cfg, err := parseConfig(configFile) - if err != nil { - log.Fatal(err) - } - - err = createDirs(path.Join(cfg.CertDir, cfg.App)) - if err != nil { - log.Fatal(err.Error()) - } - - dirCSR := path.Join(cfg.CertDir, cfg.App, csrSubDir) - dirConverted := path.Join(cfg.CertDir, cfg.App, convertedSubDir) - dirDownloaded := path.Join(cfg.CertDir, cfg.App, downloadedSubDir) - - err = convertCerToPem(dirDownloaded, dirConverted) - if err != nil { - log.Fatal("convertCerToPem:", err.Error()) - } - - err = convertPemToP12(dirCSR, dirConverted, cfg.App) - if err != nil { - log.Fatal("convertPemToP12:", err.Error()) - } - - err = extractPrivateKey(dirConverted, cfg.App) - if err != nil { - log.Fatal("extractPrivateKey:", err.Error()) - } - - err = verify(dirConverted, cfg.App, cfg.AppleGateway) - if err != nil { - log.Fatal("verify:", err.Error()) - } -} - -func createDirs(dir string) error { - dirs := []string{ - path.Join(dir, csrSubDir), - path.Join(dir, convertedSubDir), - path.Join(dir, downloadedSubDir), - } - for _, dir := range dirs { - err := os.MkdirAll(dir, 0700) - if err != nil { - return err - } - } - return nil -} - -func convertCerToPem(dirDownloaded, dirConverted string) error { - // openssl x509 -inform=der -in=certs/mattermost/downloaded/aps.cer -outform=pem -out=certs/mattermost/converted/aps.pem - cmd := exec.Command("openssl", "x509", - "-inform=der", - "-in="+path.Join(dirDownloaded, apsCer), - "-outform=pem", - "-out="+path.Join(dirConverted, apsPem), - ) - err := execCommand(cmd) - if err != nil { - return err - } - return nil -} - -func convertPemToP12(dirCSR, dirConverted, app string) error { - // openssl pkcs12 -export -inkey=certs/mattermost/csr/mattermost.key -in=certs/mattermost/converted/aps.pem -out=certs/mattermost/converted/aps.p12 -clcerts -passout=pass: - cmd := exec.Command("openssl", "pkcs12", - "-export", - "-inkey="+path.Join(dirCSR, app+".key"), - "-in="+path.Join(dirConverted, apsPem), - "-out="+path.Join(dirConverted, apsP12), - "-clcerts", - "-passout=pass:", - ) - err := execCommand(cmd) - if err != nil { - return err - } - return nil -} - -func extractPrivateKey(dirConverted, app string) error { - // openssl pkcs12 -in=certs/mattermost/converted/aps.p12 -out=certs/mattermost/mattermost/converted/classic_priv.pem -nodes -clcerts -passin=pass: - cmd := exec.Command("openssl", "pkcs12", - "-in="+path.Join(dirConverted, apsP12), - "-out="+path.Join(dirConverted, app+"_priv.pem"), - "-nodes", - "-clcerts", - "-passin=pass:", - ) - err := execCommand(cmd) - if err != nil { - return err - } - return nil -} - -func verify(dirConverted, app, gateway string) error { - // openssl s_client -connect=gateway.push.apple.com:2195 -cert=certs/mattermost/mattermost/converted/aps.pem -key=certs/mattermost/mattermost/converted/classic_priv.pem - cmd := exec.Command("openssl", "s_client", - "-connect="+gateway, - "-cert="+path.Join(dirConverted, apsPem), - "-key="+path.Join(dirConverted, app+"_priv.pem"), - ) - err := execCommand(cmd) - if err != nil { - return err - } - return nil -} - -func execCommand(cmd *exec.Cmd) error { - buf, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("%s: %w", string(buf), err) - } - if len(buf) == 0 { - return nil - } - log.Printf("Result: %s\n", string(buf)) - return nil -} diff --git a/cmd/renew_apple_cert/convert_cert/testdata/config.json b/cmd/renew_apple_cert/convert_cert/testdata/config.json deleted file mode 100644 index a632bf4..0000000 --- a/cmd/renew_apple_cert/convert_cert/testdata/config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "App": "mattermost", - "CertDir": "testdata/certs", - "AppleGateway": "gateway.push.apple.com:2195" -} diff --git a/cmd/renew_apple_cert/create_csr/config.go b/cmd/renew_apple_cert/create_csr/config.go deleted file mode 100644 index d678e36..0000000 --- a/cmd/renew_apple_cert/create_csr/config.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -package main - -import ( - "encoding/json" - "fmt" - "os" - - "github.com/kelseyhightower/envconfig" -) - -type config struct { - App string - ApplePushTopic string - Country string - Province string - Locality string - Organization string - Email string - CertDir string -} - -func parseConfig(path string) (config, error) { - var cfg config - file, err := os.Open(path) - if err != nil { - return cfg, fmt.Errorf("could not open file: %w", err) - } - defer file.Close() - - err = json.NewDecoder(file).Decode(&cfg) - if err != nil { - return cfg, fmt.Errorf("could not decode file: %w", err) - } - - if err = envconfig.Process("create_csr", &cfg); err != nil { - return cfg, err - } - - return cfg, nil -} diff --git a/cmd/renew_apple_cert/create_csr/config.sample.json b/cmd/renew_apple_cert/create_csr/config.sample.json deleted file mode 100644 index 3ebf573..0000000 --- a/cmd/renew_apple_cert/create_csr/config.sample.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "App": "mattermost", - "CertDir": "../certs", - "ApplePushTopic": "com.mattermost.Mattermost", - "Country": "US", - "Province": "California", - "Locality": "Palo Alto", - "Organization": "Mattermost, Inc.", - "Email": "email@example.com" -} \ No newline at end of file diff --git a/cmd/renew_apple_cert/create_csr/main.go b/cmd/renew_apple_cert/create_csr/main.go deleted file mode 100644 index 5ea0da8..0000000 --- a/cmd/renew_apple_cert/create_csr/main.go +++ /dev/null @@ -1,118 +0,0 @@ -package main - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/asn1" - "encoding/pem" - "flag" - "io/ioutil" - "log" - "os" - "path" -) - -const ( - csrSubDir = "csr" - downloadedSubDir = "downloaded" -) - -func main() { - var configFile string - flag.StringVar(&configFile, "config", "config/config.json", "Configuration file for create_csr.") - flag.Parse() - - runJob(configFile) -} - -// runJob is an externalized version of main to facilitate testing. -func runJob(configFile string) { - cfg, err := parseConfig(configFile) - if err != nil { - log.Fatal(err) - } - - err = createDirs(path.Join(cfg.CertDir, cfg.App)) - if err != nil { - log.Fatal(err) - } - - dirCSR := path.Join(cfg.CertDir, cfg.App, csrSubDir) - key, err := createAndWritePrivateKey(cfg.App, dirCSR) - if err != nil { - log.Fatal("createAndWritePrivateKey:", err) - } - - err = createAndWriteCSR(cfg, key, dirCSR) - if err != nil { - log.Fatal("createAndWriteCSR:", err) - } -} - -func createDirs(dir string) error { - dirs := []string{ - path.Join(dir, csrSubDir), - path.Join(dir, downloadedSubDir), - } - for _, dir := range dirs { - err := os.MkdirAll(dir, 0700) - if err != nil { - return err - } - } - return nil -} - -func createAndWritePrivateKey(app, dirCSR string) (*rsa.PrivateKey, error) { - key, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - return nil, err - } - marshaledKey := x509.MarshalPKCS1PrivateKey(key) - pemPrivateKey := pem.EncodeToMemory( - &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: marshaledKey, - }, - ) - err = ioutil.WriteFile(path.Join(dirCSR, app+".key"), pemPrivateKey, 0664) - if err != nil { - return nil, err - } - return key, err -} - -func createAndWriteCSR(cfg config, key *rsa.PrivateKey, dirCSR string) error { - subj := pkix.Name{ - CommonName: cfg.ApplePushTopic, - Country: []string{cfg.Country}, - Province: []string{cfg.Province}, - Locality: []string{cfg.Locality}, - Organization: []string{cfg.Organization}, - ExtraNames: []pkix.AttributeTypeAndValue{ - { - Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, - Value: asn1.RawValue{ - Tag: asn1.TagIA5String, - Bytes: []byte(cfg.Email), - }, - }, - }, - } - template := x509.CertificateRequest{ - Subject: subj, - SignatureAlgorithm: x509.SHA256WithRSA, - } - csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &template, key) - if err != nil { - return err - } - cr := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes}) - err = ioutil.WriteFile(path.Join(dirCSR, cfg.App+".csr"), cr, 0664) - if err != nil { - return err - } - return nil -} diff --git a/cmd/renew_apple_cert/create_csr/main_test.go b/cmd/renew_apple_cert/create_csr/main_test.go deleted file mode 100644 index a12db2e..0000000 --- a/cmd/renew_apple_cert/create_csr/main_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "os" - "path" - "testing" -) - -func TestCSRCreation(t *testing.T) { - defer os.RemoveAll(path.Join("testdata", "certs")) - runJob(path.Join("testdata", "config.json")) - if _, err := os.Stat(path.Join("testdata", "certs", "mattermost", "csr", "mattermost.key")); os.IsNotExist(err) { - t.Error(err) - } - - if _, err := os.Stat(path.Join("testdata", "certs", "mattermost", "csr", "mattermost.csr")); os.IsNotExist(err) { - t.Error(err) - } -} diff --git a/cmd/renew_apple_cert/create_csr/testdata/config.json b/cmd/renew_apple_cert/create_csr/testdata/config.json deleted file mode 100644 index ba422e1..0000000 --- a/cmd/renew_apple_cert/create_csr/testdata/config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "App": "mattermost", - "CertDir": "testdata/certs", - "ApplePushTopic": "com.mattermost.Mattermost", - "Country": "US", - "Province": "California", - "Locality": "Palo Alto", - "Organization": "Mattermost, Inc.", - "Email": "email@example.com" -} \ No newline at end of file From 23e7a1dcfaebbeb9e8dcebc3ee1ff376760e3fd6 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Wed, 6 Sep 2023 14:38:50 +0530 Subject: [PATCH 2/2] go mod tidy --- go.mod | 1 - go.sum | 2 -- 2 files changed, 3 deletions(-) diff --git a/go.mod b/go.mod index 2640d71..a2876bd 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( github.com/appleboy/go-fcm v0.1.5 github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 - github.com/kelseyhightower/envconfig v1.4.0 github.com/kyokomi/emoji v2.2.4+incompatible github.com/prometheus/client_golang v1.12.1 github.com/prometheus/common v0.32.1 diff --git a/go.sum b/go.sum index 831c7bd..554ba16 100644 --- a/go.sum +++ b/go.sum @@ -150,8 +150,6 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= -github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=