问题描述
我正在寻找有关如何使用ADFS(用户名和密码)以及MFA身份验证来获取临时访问密钥和秘密密钥以进行进一步操作的方法,以对使用ADFS认证NodeJS服务器我的AWS账户的建议。
作为参考,我正在尝试实现saml2aws在命令行界面上的功能。在这里,我想在NodeJS服务器上代替命令行界面。
任何建议将不胜感激。
到目前为止,我已经收到了下面的代码,就像我输入ADFS凭据并提交请求一样,它对我完成了一半工作,然后在我的Microsoft身份验证器应用程序上触发了要批准的通知。但是我的代码不等待验证者的响应。它只是获取网页的正文,在该正文中等待身份验证者批准。我需要某种方式使其等待身份验证器响应,这将在提交ADFS信用后为我提供SAML断言响应。
require("dotenv").config();
const AWS = require("aws-sdk");
const sts = new AWS.STS();
const request = require("request").defaults({ jar: true });
const url = require("url");
const jssoup = require("jssoup").default;
const os = require("os");
const path = require("path");
const fs = require("fs");
const ini = require("ini");
const HOME = os.homedir();
const CONfig_FILE = path.join(HOME,".aws","credentials");
let IDP_URL = process.env.IDP_URL;
let IDP_USER = process.env.IDP_USER;
let IDP_PASS = process.env.IDP_PASS;
let AWS_PROFILE = process.env.AWS_PROFILE;
console.log(IDP_USER);
function base64encode(data) {
return Buffer.from(data,"utf8").toString("base64");
}
function base64decode(data) {
return Buffer.from(data,"base64").toString("utf8");
}
function httpGet(url) {
const options = {
url,};
return new Promise((resolve,reject) => {
request.get(options,(error,response,body) => {
if (error) {
reject(error);
} else {
resolve({ response,body });
}
});
});
}
function httpPost(url,form) {
const options = {
url,form,followAllRedirects: true,reject) => {
request.post(options,body });
}
});
});
}
function getLoginData(body) {
const soup = new jssoup(body);
const forms = soup.findAll("form");
const form = forms.find((form) => form.attrs.id === "loginForm");
if (!form) {
throw new Error("LOGIN_FORM_NOT_FOUND");
}
const action = url.resolve(IDP_URL,form.attrs.action);
const inputs = {};
for (const input of form.findAll("input")) {
const name = input.attrs.name || "";
const value = input.attrs.value || "";
const namelc = name.toLowerCase();
if (namelc.includes("user")) {
inputs[name] = IDP_USER;
} else if (namelc.includes("email")) {
inputs[name] = IDP_USER;
} else if (namelc.includes("pass")) {
inputs[name] = IDP_PASS;
} else {
inputs[name] = value;
}
}
return { action,inputs };
}
function getSAMLAssertion(body) {
const soup = new jssoup(body);
const inputs = soup.findAll("input");
const saml = inputs.find((input) => input.attrs.name === "SAMLResponse");
if (!saml) {
throw new Error("SAML_ASSERTION_NOT_FOUND");
}
return base64decode(saml.attrs.value);
}
function getSAMLRoles(saml) {
const soup = new jssoup(saml);
const roles = soup
.findAll("AttributeValue")
.filter((value) => {
return (
value.parent &&
value.parent.name === "Attribute" &&
value.parent.attrs &&
value.parent.attrs.Name ===
"https://aws.amazon.com/SAML/Attributes/Role"
);
})
.map((value) => {
const [provider,role] = (value.text || "").split(",");
return { provider,role };
});
if (!roles[0]) {
throw new Error("SAML_ROLE_NOT_FOUND");
}
return roles;
}
async function getSTSToken(provider,role,assertion) {
const params = {
DurationSeconds: 3600,PrincipalArn: provider,RoleArn: role,SAMLAssertion: base64encode(assertion),reject) => {
sts.assumeRoleWithSAML(params,data) => {
if (error) {
reject(error);
} else {
resolve(data);
}
});
});
}
function saveSTSToken(filename,profile,sts) {
const readFile = () => {
try {
return ini.decode(fs.readFileSync(filename,"utf-8"));
} catch (e) {
return {};
}
};
const writeFile = (config) => {
fs.writeFileSync(filename,ini.encode(config,{ whitespace: true }));
};
const config = readFile();
const section = config[profile] || {};
const credentials = sts.Credentials || {};
section.aws_access_key_id = credentials.AccessKeyId;
section.aws_secret_access_key = credentials.SecretAccessKey;
section.aws_session_token = credentials.SessionToken;
config[profile] = section;
writeFile(config);
}
function checkUsage() {
if (!IDP_URL) {
throw new Error("IDP_URL not set!");
}
if (!IDP_USER) {
throw new Error("IDP_USER not set!");
}
if (!IDP_PASS) {
throw new Error("IDP_PASS not set!");
}
if (!AWS_PROFILE) {
throw new Error("AWS_PROFILE not set!");
}
}
(async function main() {
try {
console.log(`aws-saml-session started.`);
checkUsage();
console.log(`Logging into SAML provider...`);
const resp1 = await httpGet(IDP_URL);
const data = getLoginData(resp1.body);
// This is the place its not waiting and getting me body of the page
//where it needs to wait and get me SAML response
```const resp2 = await httpPost(data.action,data.inputs);
const saml = getSAMLAssertion(resp2.body);```
const roles = getSAMLRoles(saml);
const { provider,role } = roles[0];
console.log(`Assuming role: ${role}...`);
const sts = await getSTSToken(provider,saml);
console.log(`Saving credentials: ${AWS_PROFILE}...`);
saveSTSToken(CONfig_FILE,AWS_PROFILE,sts);
console.log("Done.");
} catch (e) {
console.log("ERROR:",e.message);
}
})();
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)