Securing Node-RED

Sunyoung·2021년 4월 9일
0

https://nodered.org/docs/user-guide/runtime/securing-node-red

2021.04.09 기준 문서

기본적으로 Node-RED 편집기는 보안되지 않습니다. IP 주소에 액세스 할 수있는 사람은 누구나 편집기에 액세스하고 변경 사항을 배포 할 수 있습니다. 신뢰할 수있는 네트워크에서 실행중인 경우에만 적합합니다. 이 가이드에서는 Node-RED를 보호하는 방법을 설명합니다. 보안은 세 부분으로 나뉩니다.

  • HTTPS 접근 가능
  • 관리자 API 와 에디터 보안
  • HTTP 노드들과 노드레드 대시보드 보안

HTTPS 접근가능
HTTPS에 노드레드 에디터에 접근하기 위해서는 기본 HTTP 보다 HTTPS 구성 옵션을 설정 파일에서 사용합니다.
HTTPS 옵션을 고정 할 수 있으며 1.1.0 버전 부터 옵션을 함수로 리턴 받을 수 있습니다.
모든 옵션에 대해서는 문서화된 내용을 참고 합니다 작게는 이런 옵션들을 필요로 합니다

key - String 또는 Buffer로 제공된 PEM 포맷 개인키
cert - String 또는 Buffer로 제공된 PEM 포맷 인증서 체인

인증서를 생성하는 방법은 이 가이드를 참고하세요 노드 레드의 기본 설정은 https 부분 코멘트를 로컬 파일의 인증서로 사용됩니다.

https: {
    key: require("fs").readFileSync('privkey.pem'),
    cert: require("fs").readFileSync('cert.pem')
},

노드레드 1.1.0부터

HTTPS 속성 함수에서 옵션 항목을 리턴 받을 수 있습니다. 이 함수는 옵션 개체로 해결할 Promise를 선택적으로 반환하여 비동기 적으로 완료 할 수 있습니다.

https: function() {
    return new Promise((resolve, reject) => {
        var key, cert;
        // Do some work to obtain valid certificates
        // ...
        resolve({
            key: key
            cert: ccert
        })
    });
}

HTTPS 인증서를 재구성하기

1.1.0 버전 부터 Node-RED를 다시 시작하지 않고도 주기적으로 HTTPS 인증서를 새로 고치도록 Node-RED를 구성 할 수 있습니다.

  1. Node.js 11 버전 이상 사용 해야 합니다
  2. HTTPS 설정은 업데이트 된 인증서들을 의 함수들을 불러와야 합니다
  3. httpsRefreshInterval을 Node-RED가 업데이트 된 세부 정보를 얻기 위해 https 함수를 호출해야하는 빈도 (시간)로 설정합니다.

https 함수는 현재 인증서가 다음 httpsRefreshInterval 기간 내에 만료되는지 여부를 확인하고, 그렇다면 새 인증서를 생성해야합니다.
업데이트가 필요하지 않은 경우 함수는 undefined 또는 null을 반환 할 수 있습니다.

에디터&관리자 API 보안
에디터와 관리자 API는 두가지 권한을 지원합니다

  • 이름/패스워드의 권한
  • Twitter 또는 GitHub와 같은 OAuth / OpenID 공급자에 대한 인증

이름/사용자 기반 권한
설정 파일 안에 adminAuth 속성에서 에디터와 관리자API 에 사용자권한을 가능하게 할수 있습니다.

adminAuth: {
    type: "credentials",
    users: [
        {
            username: "admin",
            password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.",
            permissions: "*"
        },
        {
            username: "george",
            password: "$2b$08$wuAqPiKJlVN27eF5qJp.RuQYuy6ZYONW7a/UWYxDTtwKFCdB8F19y",
            permissions: "read"
        }
    ]
}

users 속성은 사용자 정보의 배열입니다. 다른 허가사항을 가져야 하는 각각의 여러 사용자들을 정의 해야 할 경우에 해당합니다
이 예제는 두개의 다른 유저를 정의합니다 하나는 admin으로 에디터 포함 모든 것이 가능한 항목과 다른 george는 읽기전용권한을 가집니다.
패스워드 들은 bcrypt 알고리즘을 사용한 해시가 되어있습니다

이전 노드 레드 버전에서는 httpAdminAuth 에서 HTTP 기본 권한이 에디터가 가능 했었지만 이 옵션은 deprecated 되었고 지금은 사용되지 않습니다

패스워드 해시를 생성

1.1.0또는 그 이후 버전에서는 명령어를 이렇게 사용합니다

node-red admin hash-pw

이전 버전에서는 또 이렇게 사용합니다

  • node-red-admin 명령툴과 명렁어 사용의 설치는 나누어져 있습니다
 node-red-admin hash-pw
  • 또는 노드 레드 디렉토리에서 해당 명령으로 인스톨 할 수 있습니다
node -e "console.log(require('bcryptjs').hashSync(process.argv[1], 8));" your-password-here

모든 경우에 해시 버전의 패스워드들을 설정 파일에 붙여 넣을 수 있습니다

OAuth/OpenID 기반 권한

외부 인증 소스를 사용할때에는 passport.js에서 제공되는 여러 범위의 기능들을 사용 할 수 있습니다.
노드 레드 인증 모듈은 트위터와 깃헙에서 사용 가능합니다. 쉽게 사용할 상세 기능들을 구성해 놓았습니다. 그리고 strategy에서 인증하기 위한 템플릿으로 사용할 수도 있습니다.
다음 예제는 우리가 제공하는 인증 모듈을 사용하지 않고 Twitter에 대해 인증하도록 구성하는 방법을 보여줍니다.

adminAuth: {
    type:"strategy",
    strategy: {
        name: "twitter",
        label: 'Sign in with Twitter',
        icon:"fa-twitter",
        strategy: require("passport-twitter").Strategy,
        options: {
            consumerKey: TWITTER_APP_CONSUMER_KEY,
            consumerSecret: TWITTER_APP_CONSUMER_SECRET,
            callbackURL: "http://example.com/auth/strategy/callback",
            verify: function(token, tokenSecret, profile, done) {
                done(null, profile);
            }
        },
    },
    users: [
       { username: "knolleary",permissions: ["*"]}
    ]
};

strategy 속성은 다음과 같은 옵션을 가집니다

  • name - 사용할 passport 전략의 이름
  • strategy - passport 전략 모듈
  • label/icon - 로그인 페이지, icon fontawesome 아이콘 이름 가능
  • options - 패스포트 전략이 생성 될 때 전달되는 옵션 객체. 필요한 사항은 전략의 자체 문서를 참조하십시오. callbackURL의 노드는 아래를 참조하십시오.
  • verify - 전략에서 사용하는 검증 기능. 사용자가 유효한 경우 두 번째 인수로 사용자 프로필을 사용하여 done을 호출해야합니다. 유효한 사용자 목록을 확인하는 데 사용되는 사용자 이름 속성이 있어야합니다. Passport는 사용자 프로필 개체를 표준화하려고 시도하므로 대부분의 전략에서이 속성을 제공합니다.

전략에서 사용하는 callbackURL은 인증 공급자가 인증 시도 후 리디렉션되는 위치입니다. /auth/strategy/callback이 경로에 추가 된 Node-RED 편집기의 URL이어야합니다. 예를 들어 http://localhost:1880 에서 편집기에 액세스하는 경우 http://localhost:1880/auth/strategy/callback 을 사용합니다.

기본 사용자 설정

다음 예제 설정은 로그인 한 사용자들만 볼 수 있는 에디터 입니다. 어떤 경우에는 모든 경우에 허가 레벨을 주고싶을 경우가 있습니다. 전형적으로 이것은 읽기 전용 권한의 에디터가 됩니다. 이경우 default 속성을 adminAuth 설정에 추가해서 명시하여 설정합니다.

adminAuth: {
    type: "credentials",
    users: [ /* list of users */ ],
    default: {
        permissions: "read"
    }
}

사용자 허가
앞선 0.14 버전에서 사용자는 두가지의 허용을 할 수 있습니다

  • * - 모든 접근
  • read - 읽기 전용 접근

0.14 에서의 허가는 지원에서 더 좋은 효과가 있습니다. 해당 속성은 이전의 단일 string 이거나 또는 여러 허가를 포함한 배열을 가질 수 있습니다
Admin API의 각 메소드는 액세스하는 데 필요한 권한 수준을 정의합니다. 권한 모델은 리소스 기반입니다. 예를 들어 현재 흐름 구성을 가져 오려면 사용자에게 flows.read 권한이 필요합니다. 그러나 흐름을 업데이트하려면 flows.write 권한이 필요합니다.

유효 토큰

기본적으로 액세스 토큰은 생성 후 7 일 후에 만료됩니다. 현재이 기간을 연장하기 위해 토큰 새로 고침을 지원하지 않습니다.
만료 시간은 adminAuth 설정의 sessionExpiryTime 속성을 설정하여 사용자 지정할 수 있습니다. 토큰의 유효 기간을 초 단위로 정의합니다. 예를 들어 토큰이 1 일 후에 만료되도록 설정하려면 다음을 수행하십시오.

adminAuth: {
    sessionExpiryTime: 86400,
    ...
}

관리 API 에 접근

adminAuth 속성셋은, adminAPI 문서에 API 접근에 대한 내용이 있습니다

커스텀 사용자 권한
설정파일의 사용자 하드코드 보다는 사용자 권한에 대한 커스텀 코드 플러그인을 사용합니다. 존재하는 권한 스키마의 병합으로 가능합니다.
다음 예제는 외부 모듈이 커스텀 권한 코드로 제공될수 있게 구성되어 있습니다

  • /user-authentication.js 에 저장되어 있습니다.

    module.exports = {
       type: "credentials",
       users: function(username) {
           return new Promise(function(resolve) {
               // Do whatever work is needed to check username is a valid
               // user.
               if (valid) {
                   // Resolve with the user object. It must contain
                   // properties 'username' and 'permissions'
                   var user = { username: "admin", permissions: "*" };
                   resolve(user);
               } else {
                   // Resolve with null to indicate this user does not exist
                   resolve(null);
               }
           });
       },
       authenticate: function(username,password) {
           return new Promise(function(resolve) {
               // Do whatever work is needed to validate the username/password
               // combination.
               if (valid) {
                   // Resolve with the user object. Equivalent to having
                   // called users(username);
                   var user = { username: "admin", permissions: "*" };
                   resolve(user);
               } else {
                   // Resolve with null to indicate the username/password pair
                   // were not valid.
                   resolve(null);
               }
           });
       },
       default: function() {
           return new Promise(function(resolve) {
               // Resolve with the user object for the default user.
               // If no default user exists, resolve with null.
               resolve({anonymous: true, permissions:"read"});
           });
       }
    }
  • setting.js 에 모듈에 adminAuth 속성 내에 설정 되어 있습니다

커스텀 허가 토큰

1.1.0 노드레드 버전 부터 자신의 고유 토큰이 필요한 몇 상황에서는 노드레드로 부터 생성하지 마십시오 예를들면

  • OAuth 기반 사용자 인증을 사용하려고하지만 OAuth에 필요한 대화 형 인증 단계를 수행 할 수없는 관리 API에 대한 자동화 된 액세스도 필요할때
  • 사용자가 이미 로그인되어있는 기존 시스템에 Node-RED를 통합하고 편집기에 액세스 할 때 다시 로그인하지 않기를 원할때

adminAuth 설정에는 토큰 기능이 포함될 수 있습니다. 이 함수는 관리 API에 대한 요청에 Node-RED가 자체 인증 토큰으로 인식하는 인증 토큰이 포함되어 있지 않은 경우 호출됩니다. 요청에 제공된 토큰이 전달되고 인증 된 사용자로 해결되는 Promise를 반환하거나 토큰이 유효하지 않은 경우 null을 반환해야합니다.

adminAuth: {
  ...
  tokens: function(token) {
      return new Promise(function(resolve, reject) {
          // Do whatever work is needed to check token is valid
          if (valid) {
              // Resolve with the user object. It must contain
              // properties 'username' and 'permissions'
              var user = { username: 'admin', permissions: '*' };
              resolve(user);
          } else {
              // Resolve with null as this user does not exist
              resolve(null);
          }
      });
  },
  ...
}

기본적으로 Authorization http 헤더를 사용하고 Bearer 유형 토큰을 예상합니다. 토큰 값만 함수에 전달합니다. Bearer 유형 토큰이 아닌 경우 Authorization 헤더의 전체 값이 유형과 값을 모두 포함하는 함수에 전달됩니다.

다른 HTTP 헤더를 사용하려면 tokenHeader 설정을 사용하여 사용할 헤더를 식별 할 수 있습니다.

  adminAuth: {
    ...
    tokens: function(token) {
        ...
    },
    tokenHeader: "x-my-custom-token"
}

커스텀 토큰 에디터로 접근

로그인 프롬프트없이 사용자 정의 토큰을 사용하여 편집기에 액세스하려면 access_token = <ACCESS_TOKEN>을 URL에 추가하십시오. 편집기는 해당 토큰을 로컬에 저장하고 향후 모든 요청에 사용합니다.

HTTP 노드 보안

HTTP In 노드에 의해 노출 된 경로는 기본 인증을 사용하여 보호 할 수 있습니다.

settings.js 파일의 httpNodeAuth 속성을 사용하여 경로에 액세스 할 수있는 단일 사용자 이름과 암호를 정의 할 수 있습니다.

httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."},

pass 속성은 adminAuth와 동일한 형식을 사용합니다. 자세한 정보는 비밀번호 해시 생성을 참조하십시오.

httpStatic 속성으로 정의 된 모든 정적 콘텐츠에 대한 액세스는 동일한 형식을 사용하는 httpStaticAuth 속성을 사용하여 보호 할 수 있습니다.

참고 : Node-RED의 이전 릴리스에서 pass 속성은 MD5 해시로 예상되었습니다. 이것은 암호화 적으로 안전하지 않으므로 adminAuth에서 사용하는 bcrypt로 대체되었습니다. 이전 버전과의 호환성을 위해 MD5 해시는 계속 지원되지만 권장되지는 않습니다.

맞춤형 미들웨어
모든 HTTP In 노드 앞에 추가 될 사용자 지정 HTTP 미들웨어를 제공 할 수 있으며 Node-RED 1.1.0부터 모든 관리자 / 편집기 경로 앞에 추가 할 수 있습니다.

http-in 노드 용 사용자 지정 미들웨어
HTTP In 노드의 경우 미들웨어가 httpNodeMiddleware 설정으로 제공됩니다.

다음 설정은 http-in 노드에서 HTTP 액세스 속도를 제한하는 예입니다.

이 구성을 사용하면 http-in 노드로 시작하는 흐름이 처리하는 데 시간이 걸리는 경우에도 Node-RED 프로세스는 메모리 소모를 방지 할 수 있습니다. 제한에 도달하면 엔드 포인트는 기본 메시지 "너무 많은 요청입니다. 나중에 다시 시도하십시오."를 반환합니다.

관리자 API 용 커스텀 미들웨어
관리자 / 편집기 경로의 경우 미들웨어는 httpAdminMiddleware 설정으로 제공됩니다.

예를 들어, 다음 미들웨어를 사용하여 모든 관리자 / 편집기 요청에 X-Frame-Options http 헤더를 설정할 수 있습니다. 이것은 편집기가 다른 페이지에 임베드되는 방법을 제어하는 데 사용할 수 있습니다.

httpAdminMiddleware: function(req, res, next) {
    // Set the X-Frame-Options header to limit where the editor
    // can be embedded
    res.set('X-Frame-Options', 'sameorigin');
    next();
},
profile
배워서 남주자

0개의 댓글