package server import ( "bytes" "context" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" "encoding/json" "encoding/pem" "errors" "fmt" "io/ioutil" "net/http" "time" "github.com/fleetdm/fleet/v4/pkg/fleethttp" ) // GenerateRandomText return a string generated by filling in keySize bytes with // random data and then base64 encoding those bytes func GenerateRandomText(keySize int) (string, error) { key := make([]byte, keySize) _, err := rand.Read(key) if err != nil { return "", err } return base64.StdEncoding.EncodeToString(key), nil } func httpSuccessStatus(statusCode int) bool { return statusCode >= 200 && statusCode <= 299 } func PostJSONWithTimeout(ctx context.Context, url string, v interface{}) error { jsonBytes, err := json.Marshal(v) if err != nil { return err } client := fleethttp.NewClient(fleethttp.WithTimeout(30 * time.Second)) req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(jsonBytes)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return fmt.Errorf("failed to POST to %s: %s, request-size=%d", url, err, len(jsonBytes)) } defer resp.Body.Close() if !httpSuccessStatus(resp.StatusCode) { body, _ := ioutil.ReadAll(resp.Body) return fmt.Errorf("error posting to %s: %d. %s", url, resp.StatusCode, string(body)) } return nil } // TODO: Consider moving other crypto functions from server/mdm/apple/util to here // DecodePrivateKeyPEM decodes PEM-encoded private key data. func DecodePrivateKeyPEM(encoded []byte) (*rsa.PrivateKey, error) { block, _ := pem.Decode(encoded) if block == nil { return nil, errors.New("no PEM-encoded data found") } if block.Type != "RSA PRIVATE KEY" { return nil, fmt.Errorf("unexpected block type %s", block.Type) } return x509.ParsePKCS1PrivateKey(block.Bytes) }