<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=939333007162424&amp;ev=PageView&amp;noscript=1">
 

    Google Form과 NAC REST API 를 이용한 IP 신청
    (Sheet 버전)

    제품을 개발할 때 다양한 고객들의 요구 사항을 모두 수용하기는 현실적으로 어렵습니다. 하지만 연동을 위한 API 들이 추가되고 편하고 접근성이 좋은 서비스들이 시중에 나와있기 때문에 이들을 이용하여 고객의 요구 사항을 직접 구현해볼 수 있습니다.

    이에 Google Form과 RESTful API를 활용한 고객 맞춤 서비스 아이디어를 소개하려고 합니다. 본 문서는 이 서비스의 개념, 시나리오, 구현 방법 등을 상세히 설명하여 NAC와 IP 신청 시스템을 운영 시 참고하실 수 있도록 작성되었습니다.

     

    개념 소개

    1. Genian NAC의 RESTful API
      내부 자산과 사용자를 보호하고 기업 자원을 안전하게 사용할 수 있도록 지원하는 유무선 네트워크 접근제어 솔루션인 Genian NAC 에서는 해당 자원들을 접근하고 통제할 수 있는 기능 및 IP 신청 등을 REST API로 제공하고 있습니다.

    2. Google Form
      Google Form은 구글에서 제공하는 무료 웹 기반 설문조사 도구 입니다. 간편한 설문지 생성, 실시간 응답 수집, 다양한 공유 옵션, 통계분석 기능과 부가기능을 제공합니다. 설문지 생성 시 Script가 동작하도록 설정할 수 있으며 구글폼을 통해 사용자에게 IP 신청을 받는 용도로 활용합니다.

    3. Google Apps Script
      Google에서 제공하는 클라우드 기반 스크립팅 플랫폼 입니다. 이를 활용하여 Google 제품군과 통합하여 맞춤형 애플리케이션을 빌드할 수 있습니다.
      Google 워크스페이스, Gmail, 드라이브, Sheets 등의 통합환경에서 Javascript 기반 스크립트를 작성하며 특정 이벤트에 맞춰 스크립트를 실행하는 트리거와 이벤트 및 API 연동을 클라우드 기반으로 무료 및 저비용으로 사용할 수 있는 도구 입니다.

     

    시나리오

    본 문서에서 다루는 시나리오는 이와 같습니다.

    1. 사용자가 Google Form 으로 신청 내용 작성
    2. Google Sheets 에 신청 내용 등록
    3. 신청한 내용을 바탕으로 IP 신청
    4. 관리자가 Google Sheets에서 승인으로 값 변경
    5. 관리자가 승인한 IP 신청서 승인

    간략하게 그림으로 표현하면 아래와 같습니다.

     Google Form과 RESTful API를 활용한 고객 맞춤 서비스 시나리오
    [그림 1] Google Form과 RESTful API를 활용한 고객 맞춤 서비스 시나리오

     

    사전 준비 및 구현

    1. Genian NAC

    Google Apps Script에서 NAC의 API를 호출하기 위해서는 네트워크 접근이 가능해야 하기 때문에 클라우드 기반의 NAC 환경이거나 NAC에 접근할 수 있도록 도메인 설정을 먼저 해야 합니다. 여기에서는 접근 편의성을 위해 Test용 Cloud NAC를 생성하여 진행합니다.

    (1) Cloud NAC 사이트 생성

    Cloud NAC 사이트 생성[그림 2] Cloud NAC 사이트 생성


    (2) 센서 설정 및 API Key 발급

    • IP 신청을 하기 위해서는 관리하고 있는 네트워크에 NAC 센서를 연결하여 생성한 사이트에 등록해야 합니다. NAC 센서 생성 및 설정은 Genian NAC Documents를 참고하세요.

    • API 연동을 위해서는 관리자의 API Key를 생성해야 합니다.
      관리 > 사용자 > 관리자의 상세 화면에서 API Key를 생성할 수 있습니다.

    NAC API Key 생성[그림 3] API Key 생성 화면

    •   해당 Key는 생성할 때만 확인할 수 있기 때문에 분실하지 않도록 보관합니다.

     

    (3) 센서 Node ID 확인

    • IP 신청을 할 때 NAC 센서를 선택해야 하는데 선택할 때의 Key가 되는 Node ID를 확인합니다.
    • 시스템 > 센서 설정 > 센서 상세 화면의 노드 ID 확인

    노드 ID 확인 화면[그림 4] 노드 ID 확인 화면



    2. Google Form

    (1) 사용자에게 IP 신청을 받을 수 있는 Google Form의 항목을 설정합니다.

    • Google Drive 의 메뉴에서 Google 설문지 메뉴 선택

    구글 설문지[그림 5] Google Drive 설문지


    (2) IP 신청서 작성 시 필수 입력이 되는 부분을 설정합니다.

    • 각 사이트마다 요구 사항은 다를 수 있으며 환경에 맞게 구성합니다.
    • 이번 문서에서는 기본적인 항목을 기반으로 설정하였고 설정 사항은 아래와 같습니다.

    사용위치 : 드롭다운 사용하고 있는 센서를 추가합니다. 여러 항목을 선택할 수 있도록 드롭다운을 사용했으며 구분을 위해 IP 주소를 라벨로 지정했습니다.
    사용자 ID : 단답형 텍스트 사용자의 ID를 입력합니다.
    용도 : 드롭다운 유동, 고정 IP 사용인지 용도를 선택할 수 있습니다.
    IP 주소 : 단답형 텍스트 고정 IP 용도인 경우 IP를 입력받습니다.
    MAC 주소 :단답형 텍스트 고정 IP 용도인 경우 MAC 주소를 입력 받습니다.
    이메일 : 단답형 텍스트 신청 결과를 받을 이메일 주소를 입력 받습니다.

     

    IP 신청서 화면[그림 6] IP 신청서 화면

    (3) 응답결과에 대한 Sheets를 생성합니다.

    • 응답 > Sheets에서 보기 선택

    IP 신청 응답결과 화면
    [그림 7] IP신청 응답결과 화면


    (4) Sheets 에서 컬럼 두개를 추가 합니다.

    IP 신청 결과 Sheets 화면[그림 8] IP 신청 결과 Sheets 화면

    ① 승인여부 컬럼
    관리자가 승인 여부를 선택할 수 있도록 컬럼을 추가합니다. (드롭다운 메뉴로 추가하면 편리합니다.)


    Sheet 드롭다운 메뉴 추가[그림 9] Sheet 드롭다운 메뉴 추가


    ② idx 컬럼
    신청서 추가 후 발급받은 idx 값을 업데이트 할 컬럼 입니다.



    3. Apps Script

    • 설문이 작성되어 시트에 내용이 저장될 때마다 실행될 스크립트를 작성합니다.
    • 실행할 스크립트 종류는 두 종류 입니다.
      ① 신청서 작성 시 신청서 등록 스크립트
      ② 관리자 승인 시 신청서 승인 스크립트

     

    (1) Sheets 메뉴 > 확장 프로그램 > Apps Script 를 선택합니다.

    Apps Script 확장 프로그램[그림 10] Apps Script 확장 프로그램

     

    (2) 스크립트를 작성하기 전 NAC의 Swagger 페이지에서 사용할 API를 확인합니다.


    Genian NAC의 Swagger 페이지 화면[그림 11] Genian NAC의 Swagger 페이지 화면

    • 생성과 승인을 하기 위해 POST /mc2/rest/applications/ips(신청서 생성) 와 PUT /mc2/rest/applications/ips/신청서idx(신청서 상태 수정) API를 확인합니다.

     

    (3) Google form이 작성될 때마다 실행될 스크립트를 작성합니다.

    • IP 신청서 등록

    function onFormSubmit(e) {
         const itemResponses = e.namedValues;

          // 관리자의 API Key를 생성한 뒤 api 호출 시 사용할 수 있도록 선언한다.
          const API_KEY = "[apiKey]"
          // REST API 를 호출할 url
          const url = "https://[도메인]/mc2/rest/applications/ips";
      
          const applyResJson = applyIpApplication(url, API_KEY, itemResponses);
          if(applyResJson !==  null) {
              const idx = applyResJson.ipApps[0].idx;
              const sheet = e.range.getSheet();
              const row = e.range.getRowIndex();
              sheet.getRange(row, 9).setValue(idx);
           }
        }

    /**
      * IP 신청서 신청 후 응답값을 json 객체로 반환
      */
    function applyIpApplication(_url, apiKey, itemResponses) {
         const url = _url + "?apiKey=" + apiKey;
         const payload = getApplicationPayload(itemResponses);

          // REST API 호출
          const options = {
             "method": "POST",
             "contentType": "application/json;charset=UTF-8",
             "headers": {
                  "accept": "application/json;charset=UTF-8"
             },
             "payload": payload
           };
          const response = UrlFetchApp.fetch(url, options);
          let resJson = null;
          try {
              resJson = JSON.parse(response.getContentText());
          } catch(e) {
              resJson = null;
          }
          return resJson;
      
       }

       /**
         * IP 신청서 신청 시 입력된 값을 json string 으로 변환
         */
       function getApplicationPayload(itemResponses) {
            // 센서의 nid을 가져올 수 있도록 객체로 미리 선언
           const sensorDatas = {'172.29.50.52': '0d300156-7c51-103e-8002-080027a65e65-cc2d2503'
                                                      '172.29.50.53': '0d300156-7c51-103e-8002-080027a65e65-cc2d2504'};
            // 용도의 value 값 선언
           const purposeDatas = {'유동IP사용': 'USERIP_VARIABLE'
                                                              '고정IP사용': 'USERIP_STATIC'};
            // 응답 데이터 가공
           const purposeType = itemResponses["용도"][0];
           const data = {};
           // 신규신청 : 1
           data["appType"] = 1;
           data["sensorNid"] = sensorDatas[itemResponses["사용위치"][0]];
           data["id"] = itemResponses["사용자 ID"][0];
           data["applicantId"] = itemResponses["사용자 ID"][0];
           data["purposeCode"] = purposeDatas[itemResponses["용도"][0]];
           if(purposeType === '고정IP사용') {
               data["ipStr"] = itemResponses["IP 주소"][0];
               data["mac"] = itemResponses["MAC 주소"][0];
            }
           data["alarmEmail"] = itemResponses["이메일"][0];
            const payload = JSON.stringify([
                data
            ]);
            return payload;
          }

    • function 설명

    onFormSubmit() Google form이 작성되는 실행되는 진입점이 되는 function
    applyIpApplication() 신청서 API를 호출하는 function. 작업이 완료되면 결과값을 json 형태로 리턴합니다.
    getApplicationPayload() 신청서 API 호출 시 form에 입력된 정보를 바탕으로 파라미터를 생성합니다.

    • 사전 정의한 정보

      const sensorDatas = {'172.29.50.xx': '센서 Node ID', 
                                               '172.29.50.xx': '센서 Node ID'};
      // 용도의 value 값 선언
      const purposeDatas = {'유동IP사용': 'USERIP_VARIABLE',
                                                      '고정IP사용': 'USERIP_STATIC'};
      • IP 신청을 할 때 센서의 Node ID 값을 파라미터로 전송해야 하는데 form에 Node ID를 노출하는 것은 사용자가 인식하기 어려운 정보이기 때문에 해당 부분은 치환이 될 수 있도록 js 객체로 사전에 정의해 놓았습니다.
      • 용도의 Key 값도 사용자가 선택한 라벨이 치환될 수 있도록 사전에 정의해 놓습니다.

    • IP 신청 승인

    /**
     * 시트에서 승인 컬럼 값이 변경되면 호출
     * @param {e} 이벤트 객체
     */
     function onEdit(e) {
          const sheet = e.source.getActiveSheet();
          const targetColumn = 8; // idx 컬럼
          const editedRow = e.range.getRow();
          const val = e.range.getValue();
      
          // 수정된 셀이 타겟 컬럼에 있는 경우에만 처리
          if (val === '승인') {
             const record = sheet.getRange(editedRow, 1, 1, sheet.getLastColumn()).getValues()[0];
             const idx = record[targetColumn];
             if(idx !== '') {
                 approveIpApplication(idx);
             }
           }
      }

      /**
       * IP 신청서 승인
       */
     function approveIpApplication(idx) {
          // 관리자의 API Key를 생성한 뒤 api 호출 시 사용할 수 있도록 선언한다.
          const API_KEY = "[apiKey]"
          const apiUrl = "https://[도메인]/mc2/rest/applications/ips/" + idx + "?apiKey=" + API_KEY;
          const options = {
               "method": "PUT",
               "contentType": "application/x-www-form-urlencoded",
               "headers": {
                    "accept": "application/json;charset=UTF-8"
                },
                "payload": "cmd=approve"
            };

            try {
                const response = UrlFetchApp.fetch(apiUrl, options);    
             } catch (err) {
                Logger.log("Error: " + err);
             }
        }

    • function 설명
       onEdit()
    • 시트의 컬럼값을 관리자가 수정했을때 호출되는 function
    • 관리자가 수정한 컬럼이 승인여부 컬럼이면서 승인으로 값을 변경할 경우, approveIpApplication() function을 호출한다.
    approveIpApplication()
    • 선택한 레코드의 IP 신청서를 승인한다.

     

    (4) 트리거로 등록

    • 트리거 메뉴로 이동합니다.

    Apps Script 화면[그림 12] Apps Script 화면

    • 트리거 추가

      • IP 신청서 등록 트리거 (이벤트 유형: 양식 제출 시)

    IP신청서 승인 트리거 화면 - 함수: onFormSubmit

    [그림 13] IP신청서 승인 트리거 화면 - 함수: onFormSubmit

    실행할 함수 선택 스크립트에 작성한 onFormSubmit() 선택
    실행할 배포 Head
    이벤트 소스 선택 스프레드시트에서
    이벤트 유형 선택 양식 제출 시

     

      • IP 신청서 등록 트리거 (이벤트 유형: 수정 시)

    IP신청서 승인 트리거 화면 - 함수: onEdit [그림 14] IP신청서 승인 트리거 화면 - 함수: onEdit

    실행할 함수 선택 스크립트에 작성한 onEdit() 선택
    실행할 배포 Head
    이벤트 소스 선택 스프레드시트에서
    이벤트 유형 선택 수정 시


    • 설문 작성 및 실행 확인
      • 실행 확인
        ① 설문을 작성 후 확인
        ② 시트에서 승인 후 확인

    Apps Script 실행 화면[그림 15] Apps Script 실행 화면

    • Logger.log 로 확인할 내용을 작성해 놓으면 실행에서 확인할 수 있습니다.

     

    (5) NAC에서 IP 신청 결과 확인

    • 관리 > 신청 > IP 사용 신청서 > 결과 조회 메뉴 이동
    • 승인된 신청서 확인

    Genian NAC - IP 사용신청서 결과 화면[그림 16] Genian NAC - IP 사용신청서 결과 화면

     

    마치며

    Google Apps Script와 Genian NAC의 REST API를 활용하여 IP 신청서를 생성하고 승인하는 과정을 경험해 보았습니다. 이처럼 Google Apps Script뿐만 아니라 REST API를 호출할 수 있는 다양한 도구들과 Genian NAC를 연동하면, 무궁무진한 활용 방법을 모색해 볼 수 있을 것입니다.

    Genian NAC의 기존 UI에서 제공하는 기능 만으로는 한계가 있지만, REST API를 적극 활용한다면 고객의 요구 사항을 보다 폭넓게 수용할 수 있을 것입니다. 예를 들어 화면 개선이 어려운 상황이라면, 연동을 통해 해결책을 모색해볼 수 있습니다.

    고객 환경에 맞는 최적의 솔루션을 제공하기 위해서는 때로는 기존의 틀을 벗어난 새로운 접근이 필요할 것입니다. 위 문서를 토대로 고객의 불편 사항을 꼭 해결할 수 있는 방안이 없는지 아이디어를 발휘해 보시면 어떨지 생각하며 이 글을 마칩니다.


     

    글쓴이.한동선

    지니언스 기술연구소에서 NAC 관련 제품 개발 및 기술 연구를 담당하고 있습니다.