Socket
Socket
Sign inDemoInstall

@netlify/functions

Package Overview
Dependencies
Maintainers
19
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@netlify/functions - npm Package Compare versions

Comparing version 0.7.3-handle-secrets.1 to 0.7.3-handle-secrets.2

2

package.json

@@ -5,3 +5,3 @@ {

"types": "./src/main.d.ts",
"version": "0.7.3-handle-secrets.1",
"version": "0.7.3-handle-secrets.2",
"description": "JavaScript utilities for Netlify Functions",

@@ -8,0 +8,0 @@ "files": [

@@ -5,2 +5,3 @@ const BUILDER_FUNCTIONS_FLAG = true

const METADATA_VERSION = 1
const ONEGRAPH_AUTHLIFY_APP_ID = '4d3de9a5-722f-4d27-9c96-2ac43c93c004'

@@ -12,2 +13,3 @@ module.exports = {

METADATA_VERSION,
ONEGRAPH_AUTHLIFY_APP_ID,
}

@@ -1,23 +0,32 @@

import { Context } from '../function/context'
import { Handler } from '../function/handler'
import * as services from './services.json'
export type ScopeInfo = {
category: string | null
scope: string
display: string
isDefault: boolean
isRequired: boolean
description: string | null
title: string | null
}
export type Services = typeof services
export type Scope = {
scope: string
scopeInfo: ScopeInfo | null
}
export type ServiceKey = keyof Services
export type Service = {
friendlyServiceName: string
service: string
isLoggedIn: boolean
bearerToken: string | null
grantedScopes: Array<Scope> | null
}
export type ServiceTokens<T extends ServiceKey> = Services[T]['tokens']
export type NetlifySecrets = {
[K in ServiceKey]?: ServiceTokens<K>
gitHub?: Service | null
spotify?: Service | null
salesforce?: Service | null
stripe?: Service | null
}
export interface ContextWithSecrets extends Context {
secrets: NetlifySecrets
}
export type HandlerWithSecrets = Handler<ContextWithSecrets>
export declare const getSecrets: () => NetlifySecrets
export declare const withSecrets: <C extends Context>(handler: HandlerWithSecrets) => Handler<C>

@@ -0,28 +1,136 @@

const { Buffer } = require('buffer')
const https = require('https')
const process = require('process')
const services = require('./services.json')
const { ONEGRAPH_AUTHLIFY_APP_ID } = require('./consts')
const getSecrets = () =>
Object.entries(services).reduce((secrets, [serviceName, service]) => {
const serviceSecrets = []
// This is so if there are no secrets we don't add an empty object
Object.entries(service.tokens).forEach(([tokenName, token]) => {
if (token in process.env) {
serviceSecrets.push([tokenName, process.env[token]])
const camelize = function (text) {
const safe = text.replace(/[-_\s.]+(.)?/g, (_, sub) => (sub ? sub.toUpperCase() : ''))
return safe.slice(0, 1).toLowerCase() + safe.slice(1)
}
// The services will be camelized versions of the OneGraph service enums
// unless overridden by the serviceNormalizeOverrides object
const serviceNormalizeOverrides = {
// Keys are the OneGraph service enums, values are the desired `secret.<service>` names
GITHUB: 'gitHub',
}
const oneGraphRequest = function (secretToken, requestBody) {
// eslint-disable-next-line node/no-unsupported-features/node-builtins
const requestBodyBuffer = Buffer.from(new TextEncoder().encode(requestBody))
return new Promise((resolve, reject) => {
const port = 443
const options = {
host: 'serve.onegraph.com',
path: `/graphql?app_id=${ONEGRAPH_AUTHLIFY_APP_ID}`,
port,
method: 'POST',
headers: {
Authorization: `Bearer ${secretToken}`,
'Content-Type': 'application/json',
Accept: 'application/json',
'Content-Length': Buffer.byteLength(requestBodyBuffer),
},
}
const req = https.request(options, (res) => {
if (res.statusCode !== 200) {
return reject(new Error(res.statusCode))
}
let body = []
res.on('data', (chunk) => {
body.push(chunk)
})
res.on('end', () => {
const data = Buffer.concat(body).toString()
try {
body = JSON.parse(data)
} catch (error) {
reject(error)
}
resolve(body)
})
})
if (serviceSecrets.length !== 0) {
// No Object.fromEntries in node < 12
return {
...secrets,
[serviceName]: serviceSecrets.reduce((acc, [tokenName, token]) => ({ ...acc, [tokenName]: token }), {}),
req.on('error', (error) => {
reject(error.message)
})
req.write(requestBodyBuffer)
req.end()
})
}
const formatSecrets = (result) => {
const services =
result.data && result.data.me && result.data.me.serviceMetadata && result.data.me.serviceMetadata.loggedInServices
if (services) {
const newSecrets = services.reduce((acc, service) => {
const normalized = serviceNormalizeOverrides[service.service] || camelize(service.friendlyServiceName)
// eslint-disable-next-line no-param-reassign
acc[normalized] = service
return acc
}, {})
return newSecrets
}
return {}
}
// Note: We may want to have configurable "sets" of secrets,
// e.g. "dev" and "prod"
const getSecrets = async () => {
const secretToken = process.env.ONEGRAPH_AUTHLIFY_TOKEN
if (!secretToken) {
console.warn(
'getSecrets is not set up. Visit Netlify Labs to enable it or trigger a new deploy if it has been enabled.',
)
return {}
}
// We select for more than we typically need here
// in order to allow for some metaprogramming for
// consumers downstream. Also, the data is typically
// static and shouldn't add any measurable overhead.
const doc = `query FindLoggedInServicesQuery {
me {
serviceMetadata {
loggedInServices {
friendlyServiceName
service
isLoggedIn
bearerToken
grantedScopes {
scope
scopeInfo {
category
scope
display
isDefault
isRequired
description
title
}
}
}
}
}
return secrets
}, {})
}`
// eslint-disable-next-line promise/prefer-await-to-callbacks
const withSecrets = (handler) => (event, context, callback) => {
const secrets = getSecrets()
return handler(event, { ...context, secrets }, callback)
const body = JSON.stringify({ query: doc })
const result = await oneGraphRequest(secretToken, body)
const newSecrets = formatSecrets(result)
return newSecrets
}

@@ -32,3 +140,2 @@

getSecrets,
withSecrets,
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc