AWS에서 만든 웹 소켓 URL이 있습니다. URL은 .net sdk를 사용하여 aws ssm start 세션에서 생성됩니다. 세션 시작 방법은 streamUrl, 토큰 및 세션 ID를 제공합니다. URL은 다음 형식입니다.
wss://ssmmessages.ap-south-1.amazonaws.com/v1/data-channel/sessionidhere?role=publish_subscribe
공유 할 수없는 "sessionidhere"위치에 실제 세션 ID가 있습니다.
xterm.js를 사용하여 웹에서 터미널을 열고 싶습니다 . xterm.js가 websocket URL에 연결하고 메시지를 보내고 출력을받을 수 있다는 것을 읽었습니다.
내 자바 스크립트 코드는 다음과 같습니다.
<!doctype html>
<html>
<head>
<link href="~/xterm.css" rel="stylesheet" />
<script src="~/Scripts/jquery-3.4.1.js"></script>
<script src="~/Scripts/bootstrap.js"></script>
<script src="~/xterm.js"></script>
</head>
<body>
<div id="terminal"></div>
<script type="text/javascript">
var term = new Terminal({
cursorBlink: "block"
});
var curr_line = "";
var entries = [];
term.open(document.getElementById('terminal'));
const ws = new WebSocket("wss://ssmmessages.ap-south-1.amazonaws.com/v1/data-channel/sessionid?role=publish_subscribe?token=tokenvalue");
var curr_line = "";
var entries = [];
term.write("web shell $ ");
term.prompt = () => {
if (curr_line) {
let data = {
method: "command", command: curr_line
}
ws.send(JSON.stringify(data));
}
};
term.prompt();
ws.onopen = function (e) {
alert("[open] Connection established");
alert("Sending to server");
var enc = new TextEncoder("utf-8"); // always utf-8
// console.log(enc.encode("This is a string converted to a Uint8Array"));
var data = "ls";
console.log(enc.encode(data));
alert(enc.encode(data));
ws.send(enc.encode(data));
alert(JSON.stringify(e));
};
ws.onclose = function (event) {
if (event.wasClean) {
alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
// e.g. server process killed or network down
// event.code is usually 1006 in this case
alert('[close] Connection died');
}
};
ws.onerror = function (error) {
alert(`[error] ${error.message}`);
};
// Receive data from socket
ws.onmessage = msg => {
alert(data);
term.write("\r\n" + JSON.parse(msg.data).data);
curr_line = "";
};
term.on("key", function (key, ev) {
//Enter
if (ev.keyCode === 13) {
if (curr_line) {
entries.push(curr_line);
term.write("\r\n");
term.prompt();
}
} else if (ev.keyCode === 8) {
// Backspace
if (curr_line) {
curr_line = curr_line.slice(0, curr_line.length - 1);
term.write("\b \b");
}
} else {
curr_line += key;
term.write(key);
}
});
// paste value
term.on("paste", function (data) {
curr_line += data;
term.write(data);
});
</script>
</body>
</html>
이제 세션이 열리고 연결이 설정되었다는 경고가 표시됩니다. 성공적으로 연결되고 있지만 명령을 보내려고 할 때마다 '데이터 채널 열기 요청에 토큰이 포함되어 있지 않습니다'라고 말하면서 연결이 닫힙니다. 3 가지 방법으로 명령을 보내려고했습니다.
첫 번째는 다음과 같습니다.
ws.send("ls")
둘째:
let data = {
method: "command", command: curr_line
}
ws.send(JSON.stringify(data));
그러나 동일한 오류가 발생합니다. 즉, 데이터 채널 열기 요청에 토큰이 포함되어 있지 않고 연결이 끊어졌습니다.
제삼:
var enc = new TextEncoder("utf-8");
var data = "ls";
ws.send(enc.encode(data));
셋째, 오류가 발생하지 않지만 출력도 얻지 못합니다 ... 누군가 도와 줄 수 있습니까?
AWS Session Manager에서 사용하는 프로토콜은 다음으로 구성됩니다.
{
"MessageSchemaVersion": "1.0",
"RequestId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"TokenValue": "<YOUR-TOKEN-VALUE>"
}
이 순간부터 프로토콜은 더 이상 JSON이 아닙니다. AWS CLI에서 SSM 세션을 시작하려는 경우 필요한 공식 Amazon SSM 에이전트 에서 구현됩니다 . 페이로드는 이 바이너리 형식 에 따라 송수신되어야 합니다.
몇 달 전과 똑같은 요구 사항이 있었으므로 AWS 세션 관리자 클라이언트 라이브러리를 만들었습니다 : https://github.com/bertrandmartel/aws-ssm-session for nodejs 및 브라우저. 프로토콜 작동 방식에 대한 자세한 정보를 원하시면 여기를 확인 하십시오.
브라우저에 사용 가능한 샘플 코드는 xterm.js를 사용합니다.
먼저 프로젝트를 복제하고 일부 유틸리티 스크립트와 함께 aws-api를 사용하여 websocket URL 및 토큰을 생성합니다.
git clone [email protected]:bertrandmartel/aws-ssm-session.git
cd aws-ssm-session
npm i
npm run build
node scripts/generate-session.js
그것은 당신에게 제공합니다 :
{
SessionId: 'xxxxxx-xxxxxxxxxxxxxx',
TokenValue: 'YOUR_TOKEN',
StreamUrl: 'wss://ssmmessages.eu-west-3.amazonaws.com/v1/data-channel/user-xxxxxxxxxxxxxx?role=publish_subscribe'
}
그런 다음 샘플 앱을 제공합니다.
npm install http-server -g
http-server -a localhost -p 3000
http : // localhost : 3000 / test / web으로 이동하여 websocket URI와 토큰을 입력합니다.
import { ssm } from "ssm-session";
var socket;
var terminal;
const termOptions = {
rows: 34,
cols: 197
};
function startSession(){
var tokenValue = document.getElementById("tokenValue").value;
var websocketStreamURL = document.getElementById("websocketStreamURL").value;
socket = new WebSocket(websocketStreamURL);
socket.binaryType = "arraybuffer";
initTerminal()
socket.addEventListener('open', function (event) {
ssm.init(socket, {
token: tokenValue,
termOptions: termOptions
});
});
socket.addEventListener('close', function (event) {
console.log("Websocket closed")
});
socket.addEventListener('message', function (event) {
var agentMessage = ssm.decode(event.data);
//console.log(agentMessage);
ssm.sendACK(socket, agentMessage);
if (agentMessage.payloadType === 1){
terminal.write(agentMessage.payload)
} else if (agentMessage.payloadType === 17){
ssm.sendInitMessage(socket, termOptions);
}
});
}
function stopSession(){
if (socket){
socket.close();
}
terminal.dispose()
}
function initTerminal() {
terminal = new window.Terminal(termOptions);
terminal.open(document.getElementById('terminal'));
terminal.onKey(e => {
ssm.sendText(socket, e.key);
});
terminal.on('paste', function(data) {
ssm.sendText(socket, data);
});
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다