Strip additional fields from HostConfiguration type

Signed-off-by: Christina Ying Wang <christina@balena.io>
This commit is contained in:
Christina Ying Wang 2024-08-14 11:07:47 -07:00
parent 78f0561988
commit e724f60beb
2 changed files with 52 additions and 69 deletions

View File

@ -47,10 +47,12 @@ export type HostProxyConfig = t.TypeOf<typeof HostProxyConfig>;
* with host-config PATCH and provided to the user with host-config GET. * with host-config PATCH and provided to the user with host-config GET.
*/ */
export const HostConfiguration = t.type({ export const HostConfiguration = t.type({
network: t.partial({ network: t.exact(
proxy: HostProxyConfig, t.partial({
proxy: t.exact(HostProxyConfig),
hostname: t.string, hostname: t.string,
}), }),
),
}); });
export type HostConfiguration = t.TypeOf<typeof HostConfiguration>; export type HostConfiguration = t.TypeOf<typeof HostConfiguration>;
@ -61,9 +63,11 @@ export type HostConfiguration = t.TypeOf<typeof HostConfiguration>;
* valid but has the correct shape. * valid but has the correct shape.
*/ */
export const LegacyHostConfiguration = t.type({ export const LegacyHostConfiguration = t.type({
network: t.partial({ network: t.exact(
t.partial({
proxy: t.record(t.string, t.any), proxy: t.record(t.string, t.any),
hostname: t.string, hostname: t.string,
}), }),
),
}); });
export type LegacyHostConfiguration = t.TypeOf<typeof LegacyHostConfiguration>; export type LegacyHostConfiguration = t.TypeOf<typeof LegacyHostConfiguration>;

View File

@ -394,19 +394,7 @@ describe('src/host-config', () => {
hostname: 'balena', hostname: 'balena',
}, },
}; };
expect(hostConfig.parse(conf)).to.deep.equal({ expect(hostConfig.parse(conf)).to.deep.equal(conf);
network: {
proxy: {
type: 'socks4',
ip: 'balena.io',
port: 1079,
login: '"baz"',
password: '"foo"',
noProxy: ['8.8.8.8'],
},
hostname: 'balena',
},
});
}); });
it('parses valid HostConfiguration with only hostname', () => { it('parses valid HostConfiguration with only hostname', () => {
@ -415,11 +403,7 @@ describe('src/host-config', () => {
hostname: 'balena2', hostname: 'balena2',
}, },
}; };
expect(hostConfig.parse(conf)).to.deep.equal({ expect(hostConfig.parse(conf)).to.deep.equal(conf);
network: {
hostname: 'balena2',
},
});
}); });
it('parses valid HostConfiguration with only proxy', () => { it('parses valid HostConfiguration with only proxy', () => {
@ -435,18 +419,7 @@ describe('src/host-config', () => {
}, },
}, },
}; };
expect(hostConfig.parse(conf)).to.deep.equal({ expect(hostConfig.parse(conf)).to.deep.equal(conf);
network: {
proxy: {
type: 'http-connect',
ip: 'test.balena.io',
port: 1081,
login: '"foo"',
password: '"bar"',
noProxy: ['3.3.3.3'],
},
},
});
}); });
it('parses valid HostConfiguration with only noProxy', () => { it('parses valid HostConfiguration with only noProxy', () => {
@ -457,13 +430,7 @@ describe('src/host-config', () => {
}, },
}, },
}; };
expect(hostConfig.parse(conf)).to.deep.equal({ expect(hostConfig.parse(conf)).to.deep.equal(conf);
network: {
proxy: {
noProxy: ['1.1.1.1', '2.2.2.2'],
},
},
});
}); });
it('parses HostConfiguration where auth fields are missing double quotes', () => { it('parses HostConfiguration where auth fields are missing double quotes', () => {
@ -480,18 +447,7 @@ describe('src/host-config', () => {
}, },
}; };
(log.warn as SinonStub).resetHistory(); (log.warn as SinonStub).resetHistory();
expect(hostConfig.parse(conf)).to.deep.equal({ expect(hostConfig.parse(conf)).to.deep.equal(conf);
network: {
proxy: {
type: 'http-connect',
ip: 'test.balena.io',
port: 1081,
login: 'foo',
password: 'bar',
noProxy: ['3.3.3.3'],
},
},
});
// Should not warn about missing double quotes // Should not warn about missing double quotes
expect(log.warn as SinonStub).to.not.have.been.called; expect(log.warn as SinonStub).to.not.have.been.called;
}); });
@ -541,18 +497,7 @@ describe('src/host-config', () => {
}, },
}; };
(log.warn as SinonStub).resetHistory(); (log.warn as SinonStub).resetHistory();
expect(hostConfig.parse(conf)).to.deep.equal({ expect(hostConfig.parse(conf)).to.deep.equal(conf);
network: {
proxy: {
type: 'socks6',
ip: 123,
port: 'abc',
login: 'user',
password: 'pass',
noProxy: true,
},
},
});
expect((log.warn as SinonStub).lastCall.args[0]).to.equal( expect((log.warn as SinonStub).lastCall.args[0]).to.equal(
'Malformed host config detected, things may not behave as expected:\n' + 'Malformed host config detected, things may not behave as expected:\n' +
'Expecting string at network.proxy.0.0.ip but instead got: 123\n' + 'Expecting string at network.proxy.0.0.ip but instead got: 123\n' +
@ -593,5 +538,39 @@ describe('src/host-config', () => {
'Could not parse host config input to a valid format', 'Could not parse host config input to a valid format',
); );
}); });
it("strips additional inputs from HostConfiguration while not erroring if some optional inputs aren't present", () => {
const conf = {
network: {
proxy: {
type: 'http-connect',
ip: 'test.balena.io',
port: 1081,
// login optional field present
// but password optional field missing
login: '"foo"',
noProxy: ['2.2.2.2'],
// local_* invalid fields present
local_ip: '127.0.0.2',
local_port: 1082,
// extra key present
extra1: 123,
},
// extra key present
extra2: true,
},
};
expect(hostConfig.parse(conf)).to.deep.equal({
network: {
proxy: {
type: 'http-connect',
ip: 'test.balena.io',
port: 1081,
login: '"foo"',
noProxy: ['2.2.2.2'],
},
},
});
});
}); });
}); });