Mail.ru рдХреНрд▓рд╛рдЙрдб рд╕реЛрд▓реНрдпреВрд╢рдиреНрд╕рдЪреНрдпрд╛ S3 рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬрдордзреАрд▓ рд╡реЗрдмрд╣реБрдХрд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдЗрд╡реНрд╣реЗрдВрдЯ-рдЪрд╛рд▓рд┐рдд рдЕрдиреБрдкреНрд░рдпреЛрдЧрд╛рдЪреЗ рдЙрджрд╛рд╣рд░рдг

Mail.ru рдХреНрд▓рд╛рдЙрдб рд╕реЛрд▓реНрдпреВрд╢рдиреНрд╕рдЪреНрдпрд╛ S3 рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬрдордзреАрд▓ рд╡реЗрдмрд╣реБрдХрд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдЗрд╡реНрд╣реЗрдВрдЯ-рдЪрд╛рд▓рд┐рдд рдЕрдиреБрдкреНрд░рдпреЛрдЧрд╛рдЪреЗ рдЙрджрд╛рд╣рд░рдг
рд░реБрдмреЗ рдЧреЛрд▓реНрдбрдмрд░реНрдЧ рдХреЙрдлреА рдорд╢реАрди

рдЗрд╡реНрд╣реЗрдВрдЯ-рдЪрд╛рд▓рд┐рдд рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рд╡рд╛рдкрд░рд▓реНрдпрд╛ рдЬрд╛рдгрд╛рд░реНтАНрдпрд╛ рд╕рдВрд╕рд╛рдзрдирд╛рдВрдЪреА рдХрд┐рдВрдордд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╡рд╛рдврд╡рддреЗ рдХрд╛рд░рдг рдЬреЗрд╡реНрд╣рд╛ рддреЗ рдЖрд╡рд╢реНрдпрдХ рдЕрд╕реЗрд▓ рддреЗрд╡реНрд╣рд╛рдЪ рд╡рд╛рдкрд░рд▓реЗ рдЬрд╛рддрд╛рдд. рд╣реЗ рдХрд╕реЗ рдЕрдВрдорд▓рд╛рдд рдЖрдгрд╛рдпрдЪреЗ рдЖрдгрд┐ рд╡рд░реНрдХрд░ рдЕреЕрдкреНрд▓рд┐рдХреЗрд╢рдиреНрд╕ рдореНрд╣рдгреВрди рдЕрддрд┐рд░рд┐рдХреНрдд рдХреНрд▓рд╛рдЙрдб рдПрдВрдЯрд┐рдЯреА рдХрд╕реЗ рддрдпрд╛рд░ рдХрд░реВ рдирдпреЗ рдпрд╛рд╕рд╛рдареА рдмрд░реЗрдЪ рдкрд░реНрдпрд╛рдп рдЖрд╣реЗрдд. рдЖрдгрд┐ рдЖрдЬ рдореА FaaS рдмрджреНрджрд▓ рдирд╛рд╣реА рддрд░ рд╡реЗрдмрд╣реБрдХреНрд╕рдмрджреНрджрд▓ рдмреЛрд▓рдгрд╛рд░ рдЖрд╣реЗ. рдореА рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬ рд╡реЗрдмрд╣реБрдХ рд╡рд╛рдкрд░реВрди рдЗрд╡реНрд╣реЗрдВрдЯ рд╣рд╛рддрд╛рд│рдгреНрдпрд╛рдЪреЗ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдЙрджрд╛рд╣рд░рдг рджрд╛рдЦрд╡рддреЛ.

рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬ рдЖрдгрд┐ рд╡реЗрдмрд╣реБрдХ рдмрджреНрджрд▓ рдХрд╛рд╣реА рд╢рдмреНрдж. рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬ рддреБрдореНрд╣рд╛рд▓рд╛ рдХреНрд▓рд╛рдЙрдбрдордзреНрдпреЗ рдХреЛрдгрддрд╛рд╣реА рдбреЗрдЯрд╛ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕рдЪреНрдпрд╛ рд╕реНрд╡рд░реВрдкрд╛рдд рд╕реНрдЯреЛрдЕрд░ рдХрд░рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рджреЗрддреЛ, рдЬреЛ S3 рджреНрд╡рд╛рд░реЗ рдкреНрд░рд╡реЗрд╢ рдХрд░рддрд╛ рдпреЗрддреЛ рдХрд┐рдВрд╡рд╛ HTTP/HTTPS рджреНрд╡рд╛рд░реЗ рджреБрд╕рд░реНрдпрд╛ API (рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреАрд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЕрд╕рддреЛ). рд╡реЗрдмрд╣реБрдХ рд╣реЗ рд╕рд╛рдорд╛рдиреНрдпрддрдГ рдХрд╕реНрдЯрдо HTTP рдХреЙрд▓рдмреЕрдХ рдЕрд╕рддрд╛рдд. рддреЗ рд╕рд╛рдорд╛рдиреНрдпрдд: рдПрдЦрд╛рджреНрдпрд╛ рдЗрд╡реНрд╣реЗрдВрдЯрджреНрд╡рд╛рд░реЗ рдЯреНрд░рд┐рдЧрд░ рдХреЗрд▓реЗ рдЬрд╛рддрд╛рдд, рдЬрд╕реЗ рдХреА рдХреЛрдб рд░реЗрдкреЙрдЬрд┐рдЯрд░реАрдордзреНрдпреЗ рдврдХрд▓рд▓рд╛ рдЬрд╛рдгреЗ рдХрд┐рдВрд╡рд╛ рдмреНрд▓реЙрдЧрд╡рд░ рдкреЛрд╕реНрдЯ рдХреЗрд▓реЗрд▓реА рдЯрд┐рдкреНрдкрдгреА. рдЬреЗрд╡реНрд╣рд╛ рдПрдЦрд╛рджреА рдШрдЯрдирд╛ рдШрдбрддреЗ, рддреЗрд╡реНрд╣рд╛ рдореВрд│ рд╕рд╛рдЗрдЯ рд╡реЗрдмрд╣реБрдХрд╕рд╛рдареА рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреЗрд▓реЗрд▓реНрдпрд╛ URL рд╡рд░ HTTP рд╡рд┐рдирдВрддреА рдкрд╛рдард╡рддреЗ. рдкрд░рд┐рдгрд╛рдореА, рддреБрдореНрд╣реА рдПрдХрд╛ рд╕рд╛рдЗрдЯрд╡рд░реАрд▓ рдЗрд╡реНрд╣реЗрдВрдЯреНрд╕ рджреБрд╕рд░реНтАНрдпрд╛ рд╕рд╛рдЗрдЯрд╡рд░ рдЯреНрд░рд┐рдЧрд░ рдХрд░реВ рд╢рдХрддрд╛ (рд╡рд┐рдХреА). рдЬрд░ рд╕реНрддреНрд░реЛрдд рд╕рд╛рдЗрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬ рдЖрд╣реЗ, рдЗрд╡реНрд╣реЗрдВрдЯ рддреНрдпрд╛рдЪреНрдпрд╛ рд╕рд╛рдордЧреНрд░реАрдордзреНрдпреЗ рдмрджрд▓ рдореНрд╣рдгреВрди рдХрд╛рд░реНрдп рдХрд░рддрд╛рдд.

рдЕрд╢рд╛ рдСрдЯреЛрдореЗрд╢рдирдЪрд╛ рд╡рд╛рдкрд░ рдХреЗрд▓рд╛ рдЬрд╛рдК рд╢рдХрддреЛ рддреЗрд╡реНрд╣рд╛ рд╕рд╛рдзреНрдпрд╛ рдкреНрд░рдХрд░рдгрд╛рдВрдЪреА рдЙрджрд╛рд╣рд░рдгреЗ:

  1. рджреБрд╕рд▒реНрдпрд╛ рдХреНрд▓рд╛рдЙрдб рд╕реНрдЯреЛрд░реЗрдЬрдордзреНрдпреЗ рд╕рд░реНрд╡ рд╡рд╕реНрддреВрдВрдЪреНрдпрд╛ рдкреНрд░рддреА рддрдпрд╛рд░ рдХрд░рдгреЗ. рдЬреЗрд╡реНрд╣рд╛ рдЬреЗрд╡реНрд╣рд╛ рдлрд╛рдЗрд▓реНрд╕ рдЬреЛрдбрд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд рдХрд┐рдВрд╡рд╛ рдмрджрд▓рд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд рддреЗрд╡реНрд╣рд╛ рдкреНрд░рддреА рддрдпрд╛рд░ рдХреЗрд▓реНрдпрд╛ рдкрд╛рд╣рд┐рдЬреЗрдд.
  2. рдЧреНрд░рд╛рдлрд┐рдХ рдлрд╛рдЗрд▓реНрд╕рдЪреНрдпрд╛ рд▓рдШреБрдкреНрд░рддрд┐рдорд╛рдВрдЪреНрдпрд╛ рдорд╛рд▓рд┐рдХреЗрдЪреА рд╕реНрд╡рдпрдВрдЪрд▓рд┐рдд рдирд┐рд░реНрдорд┐рддреА, рдЫрд╛рдпрд╛рдЪрд┐рддреНрд░рд╛рдВрдордзреНрдпреЗ рд╡реЙрдЯрд░рдорд╛рд░реНрдХ рдЬреЛрдбрдгреЗ рдЖрдгрд┐ рдЗрддрд░ рдкреНрд░рддрд┐рдорд╛ рдмрджрд▓.
  3. рдирд╡реАрди рджрд╕реНрддрдРрд╡рдЬрд╛рдВрдЪреНрдпрд╛ рдЖрдЧрдордирд╛рдмрджреНрджрд▓ рд╕реВрдЪрдирд╛ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рд╡рд┐рддрд░рд┐рдд рд▓реЗрдЦрд╛ рд╕реЗрд╡рд╛ рдХреНрд▓рд╛рдЙрдбрд╡рд░ рдЕрд╣рд╡рд╛рд▓ рдЕрдкрд▓реЛрдб рдХрд░рддреЗ рдЖрдгрд┐ рдЖрд░реНрдерд┐рдХ рджреЗрдЦрд░реЗрдЦ рдирд╡реАрди рдЕрд╣рд╡рд╛рд▓рд╛рдВрдмрджреНрджрд▓ рд╕реВрдЪрдирд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ, рддреНрдпрд╛рдВрдЪреА рддрдкрд╛рд╕рдгреА рдЖрдгрд┐ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддреЗ).
  4. рдХрд┐рдВрдЪрд┐рдд рдЕрдзрд┐рдХ рдЧреБрдВрддрд╛рдЧреБрдВрддреАрдЪреНрдпрд╛ рдкреНрд░рдХрд░рдгрд╛рдВрдордзреНрдпреЗ, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рд▓рд╛ рд╡рд┐рдирдВрддреА рддрдпрд╛рд░ рдХрд░рдгреЗ, рдЬреЗ рдЖрд╡рд╢реНрдпрдХ рдХрдВрдЯреЗрдирд░рд╕рд╣ рдПрдХ рдкреЙрдб рддрдпрд╛рд░ рдХрд░рддреЗ, рддреНрдпрд╛рд╕ рдЯрд╛рд╕реНрдХ рдкреЕрд░рд╛рдореАрдЯрд░реНрд╕ рджреЗрддреЗ рдЖрдгрд┐ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗрд▓реНрдпрд╛рдирдВрддрд░ рдХрдВрдЯреЗрдирд░ рдХреЛрд╕рд│рддреЗ.

рдЙрджрд╛рд╣рд░рдг рдореНрд╣рдгреВрди, рдЬреЗрд╡реНрд╣рд╛ Mail.ru рдХреНрд▓рд╛рдЙрдб рд╕реЛрд▓реНрдпреВрд╢рдиреНрд╕ (MCS) рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬ рдмрдХреЗрдЯрдордзреАрд▓ рдмрджрд▓ рд╡реЗрдмрд╣реБрдХ рд╡рд╛рдкрд░реВрди AWS рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬрдордзреНрдпреЗ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЭ рдХреЗрд▓реЗ рдЬрд╛рддрд╛рдд рддреЗрд╡реНрд╣рд╛ рдЖрдореНрд╣реА рдЯрд╛рд╕реНрдХ 1 рдЪрд╛ рдПрдХ рдкреНрд░рдХрд╛рд░ рдмрдирд╡реВ. рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд▓реЛрдб рдХреЗрд▓реЗрд▓реНрдпрд╛ рдкреНрд░рдХрд░рдгрд╛рдд, рд╡реЗрдмрд╣реБрдХрдЪреА рдиреЛрдВрджрдгреА рд░рд╛рдВрдЧреЗрдд рдХрд░реВрди рдЕрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХрд╛рд░реНрдп рдкреНрд░рджрд╛рди рдХреЗрд▓реЗ рдЬрд╛рд╡реЗ, рдкрд░рдВрддреБ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдХрд╛рд░реНрдпрд╛рд╕рд╛рдареА рдЖрдореНрд╣реА рдпрд╛рд╢рд┐рд╡рд╛рдп рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдХрд░реВ.

рдХрд╛рдорд╛рдЪреА рдпреЛрдЬрдирд╛

рдкрд░рд╕реНрдкрд░рд╕рдВрд╡рд╛рдж рдкреНрд░реЛрдЯреЛрдХреЙрд▓рдордзреНрдпреЗ рддрдкрд╢реАрд▓рд╡рд╛рд░ рд╡рд░реНрдгрди рдХреЗрд▓реЗ рдЖрд╣реЗ MCS рд╡рд░ S3 рд╡реЗрдмрд╣реБрдХрд╕рд╛рдареА рдорд╛рд░реНрдЧрджрд░реНрд╢рдХ. рдХрд╛рд░реНрдп рдпреЛрдЬрдиреЗрдордзреНрдпреЗ рдЦрд╛рд▓реАрд▓ рдШрдЯрдХ рдЖрд╣реЗрдд:

  • рдкреНрд░рдХрд╛рд╢рди рд╕реЗрд╡рд╛, рдЬреЗ S3 рд╕реНрдЯреЛрд░реЗрдЬ рдмрд╛рдЬреВрд▓рд╛ рдЖрд╣реЗ рдЖрдгрд┐ рд╡реЗрдмрдирд╣реВрдХ рдЯреНрд░рд┐рдЧрд░ рдЭрд╛рд▓реНрдпрд╛рд╡рд░ HTTP рд╡рд┐рдирдВрддреНрдпрд╛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рддреЗ.
  • рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд░рд╛ рд╕рд░реНрд╡реНрд╣рд░, рдЬреЗ HTTP рдкреНрд░рдХрд╛рд╢рди рд╕реЗрд╡реЗрдЪреНрдпрд╛ рд╡рд┐рдирдВрддреНрдпрд╛ рдРрдХрддреЗ рдЖрдгрд┐ рдпреЛрдЧреНрдп рдХреГрддреА рдХрд░рддреЗ. рд╕рд░реНрд╡реНрд╣рд░ рдХреЛрдгрддреНрдпрд╛рд╣реА рднрд╛рд╖реЗрдд рд▓рд┐рд╣рд┐рд▓рд╛ рдЬрд╛рдК рд╢рдХрддреЛ; рдЖрдордЪреНрдпрд╛ рдЙрджрд╛рд╣рд░рдгрд╛рдд, рдЖрдореНрд╣реА рд╕рд░реНрд╡реНрд╣рд░ Go рдордзреНрдпреЗ рд▓рд┐рд╣реВ.

S3 API рдордзреАрд▓ рд╡реЗрдмрд╣реБрдХрдЪреНрдпрд╛ рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреАрдЪреЗ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рдореНрд╣рдгрдЬреЗ рдкреНрд░рдХрд╛рд╢рди рд╕реЗрд╡реЗрд╡рд░ рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд▒реНрдпрд╛ рд╕рд░реНрд╡реНрд╣рд░рдЪреА рдиреЛрдВрджрдгреА. рд╡рд┐рд╢реЗрд╖рддрдГ, рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд░реНтАНрдпрд╛ рд╕рд░реНрд╡реНрд╣рд░рдиреЗ рдкреНрд░рдХрд╛рд╢рди рд╕реЗрд╡реЗрдХрдбреАрд▓ рд╕рдВрджреЗрд╢рд╛рдВрдЪреНрдпрд╛ рд╕рджрд╕реНрдпрддрд╛рдЪреА рдкреБрд╖реНрдЯреА рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ (рдЗрддрд░ рд╡реЗрдмрд╣реБрдХ рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреАрдордзреНрдпреЗ, рд╕рджрд╕реНрдпрддрд╛рдЪреА рдкреБрд╖реНрдЯреА рд╕рд╣рд╕рд╛ рдЖрд╡рд╢реНрдпрдХ рдирд╕рддреЗ).

рддреНрдпрд╛рдиреБрд╕рд╛рд░, рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд░реНтАНрдпрд╛ рд╕рд░реНрд╡реНрд╣рд░рдиреЗ рджреЛрди рдореБрдЦреНрдп рдСрдкрд░реЗрд╢рдиреНрд╕рдЪреЗ рд╕рдорд░реНрдерди рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ:

  • рдиреЛрдВрджрдгреАрдЪреА рдкреБрд╖реНрдЯреА рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдкреНрд░рдХрд╛рд╢рди рд╕реЗрд╡реЗрдЪреНрдпрд╛ рд╡рд┐рдирдВрддреАрд▓рд╛ рдкреНрд░рддрд┐рд╕рд╛рдж рджреНрдпрд╛,
  • рдпреЗрдгрд╛рд░реНтАНрдпрд╛ рдШрдЯрдирд╛рдВрд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рд╛.

рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд░рд╛ рд╕рд░реНрд╡реНрд╣рд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдд рдЖрд╣реЗ

рд╡реЗрдмрд╣реБрдХ рд░рд┐рд╕реАрд╡реНрд╣рд┐рдВрдЧ рд╕рд░реНрд╡реНрд╣рд░ рдЪрд╛рд▓рд╡рдгреНрдпрд╛рд╕рд╛рдареА, рддреБрдореНрд╣рд╛рд▓рд╛ рд▓рд┐рдирдХреНрд╕ рд╕рд░реНрд╡реНрд╣рд░рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЖрд╣реЗ. рдпрд╛ рд▓реЗрдЦрд╛рдд, рдЙрджрд╛рд╣рд░рдг рдореНрд╣рдгреВрди, рдЖрдореНрд╣реА MCS рд╡рд░ рдЙрдкрдпреЛрдЬрд┐рдд рдХреЗрд▓реЗрд▓реЗ рдЖрднрд╛рд╕реА рдЙрджрд╛рд╣рд░рдг рд╡рд╛рдкрд░рддреЛ.

рдЪрд▓рд╛ рдЖрд╡рд╢реНрдпрдХ рд╕реЙрдлреНрдЯрд╡реЗрдЕрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реВ рдЖрдгрд┐ рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд░рд╛ рд╕рд░реНрд╡реНрд╣рд░ рд▓рд╛рдБрдЪ рдХрд░реВ.

ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install git
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  bc dns-root-data dnsmasq-base ebtables landscape-common liblxc-common 
liblxc1 libuv1 lxcfs lxd lxd-client python3-attr python3-automat 
python3-click python3-constantly python3-hyperlink
  python3-incremental python3-pam python3-pyasn1-modules 
python3-service-identity python3-twisted python3-twisted-bin 
python3-zope.interface uidmap xdelta3
Use 'sudo apt autoremove' to remove them.
Suggested packages:
  git-daemon-run | git-daemon-sysvinit git-doc git-el git-email git-gui 
gitk gitweb git-cvs git-mediawiki git-svn
The following NEW packages will be installed:
  git
0 upgraded, 1 newly installed, 0 to remove and 46 not upgraded.
Need to get 3915 kB of archives.
After this operation, 32.3 MB of additional disk space will be used.
Get:1 http://MS1.clouds.archive.ubuntu.com/ubuntu bionic-updates/main 
amd64 git amd64 1:2.17.1-1ubuntu0.7 [3915 kB]
Fetched 3915 kB in 1s (5639 kB/s)
Selecting previously unselected package git.
(Reading database ... 53932 files and directories currently installed.)
Preparing to unpack .../git_1%3a2.17.1-1ubuntu0.7_amd64.deb ...
Unpacking git (1:2.17.1-1ubuntu0.7) ...
Setting up git (1:2.17.1-1ubuntu0.7) ...

рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд▒реНрдпрд╛ рд╕рд░реНрд╡реНрд╣рд░рд╕рд╣ рдлреЛрд▓реНрдбрд░ рдХреНрд▓реЛрди рдХрд░рд╛:

ubuntu@ubuntu-basic-1-2-10gb:~$ git clone
https://github.com/RomanenkoDenys/s3-webhook.git
Cloning into 's3-webhook'...
remote: Enumerating objects: 48, done.
remote: Counting objects: 100% (48/48), done.
remote: Compressing objects: 100% (27/27), done.
remote: Total 114 (delta 20), reused 45 (delta 18), pack-reused 66
Receiving objects: 100% (114/114), 23.77 MiB | 20.25 MiB/s, done.
Resolving deltas: 100% (49/49), done.

рдЪрд▓рд╛ рд╕рд░реНрд╡реНрд╣рд░ рд╕реБрд░реВ рдХрд░реВрдпрд╛:

ubuntu@ubuntu-basic-1-2-10gb:~$ cd s3-webhook/
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80

рдкреНрд░рдХрд╛рд╢рди рд╕реЗрд╡реЗрдЪреА рд╕рджрд╕реНрдпрддрд╛ рдШреНрдпрд╛

рддреБрдореНрд╣реА API рдХрд┐рдВрд╡рд╛ рд╡реЗрдм рдЗрдВрдЯрд░рдлреЗрд╕рджреНрд╡рд╛рд░реЗ рддреБрдордЪрд╛ рд╡реЗрдмрд╣реБрдХ рд░рд┐рд╕реАрд╡реНрд╣рд┐рдВрдЧ рд╕рд░реНрд╡реНрд╣рд░ рдиреЛрдВрджрдгреА рдХрд░реВ рд╢рдХрддрд╛. рд╕рд╛рдзреЗрдкрдгрд╛рд╕рд╛рдареА, рдЖрдореНрд╣реА рд╡реЗрдм рдЗрдВрдЯрд░рдлреЗрд╕рджреНрд╡рд╛рд░реЗ рдиреЛрдВрджрдгреА рдХрд░реВ:

  1. рдЪрд▓рд╛ рдмрд╛рджрд▓реНрдпрд╛ рд╡рд┐рднрд╛рдЧрд╛рдд рдЬрд╛рдКрдпрд╛ рдирд┐рдпрдВрддреНрд░рдг рдХрдХреНрд╖рд╛рдд.
  2. рдмрдХреЗрдЯрд╡рд░ рдЬрд╛ рдЬреНрдпрд╛рд╕рд╛рдареА рдЖрдореНрд╣реА рд╡реЗрдмрд╣реБрдХ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░реВ рдЖрдгрд┐ рдЧрд┐рдпрд░рд╡рд░ рдХреНрд▓рд┐рдХ рдХрд░рд╛:

Mail.ru рдХреНрд▓рд╛рдЙрдб рд╕реЛрд▓реНрдпреВрд╢рдиреНрд╕рдЪреНрдпрд╛ S3 рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬрдордзреАрд▓ рд╡реЗрдмрд╣реБрдХрд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдЗрд╡реНрд╣реЗрдВрдЯ-рдЪрд╛рд▓рд┐рдд рдЕрдиреБрдкреНрд░рдпреЛрдЧрд╛рдЪреЗ рдЙрджрд╛рд╣рд░рдг

рд╡реЗрдмрд╣реБрдХреНрд╕ рдЯреЕрдмрд╡рд░ рдЬрд╛ рдЖрдгрд┐ рдЬреЛрдбрд╛ рдХреНрд▓рд┐рдХ рдХрд░рд╛:

Mail.ru рдХреНрд▓рд╛рдЙрдб рд╕реЛрд▓реНрдпреВрд╢рдиреНрд╕рдЪреНрдпрд╛ S3 рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬрдордзреАрд▓ рд╡реЗрдмрд╣реБрдХрд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдЗрд╡реНрд╣реЗрдВрдЯ-рдЪрд╛рд▓рд┐рдд рдЕрдиреБрдкреНрд░рдпреЛрдЧрд╛рдЪреЗ рдЙрджрд╛рд╣рд░рдг
рдлреАрд▓реНрдб рднрд░рд╛:

Mail.ru рдХреНрд▓рд╛рдЙрдб рд╕реЛрд▓реНрдпреВрд╢рдиреНрд╕рдЪреНрдпрд╛ S3 рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬрдордзреАрд▓ рд╡реЗрдмрд╣реБрдХрд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдЗрд╡реНрд╣реЗрдВрдЯ-рдЪрд╛рд▓рд┐рдд рдЕрдиреБрдкреНрд░рдпреЛрдЧрд╛рдЪреЗ рдЙрджрд╛рд╣рд░рдг

рдЖрдпрдбреА тАФ рд╡реЗрдмрд╣реБрдХрдЪреЗ рдирд╛рд╡.

рдЗрд╡реНрд╣реЗрдВрдЯ - рдХреЛрдгрддреНрдпрд╛ рдШрдЯрдирд╛ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рд╛рдпрдЪреНрдпрд╛ рдЖрд╣реЗрдд. рдЖрдореНрд╣реА рдлрд╛рдпрд▓реАрдВрд╕рд╣ рдХрд╛рд░реНрдп рдХрд░рддрд╛рдирд╛ (рдЬреЛрдбрдгреЗ рдЖрдгрд┐ рд╣рдЯрд╡рдгреЗ) рд╕рд░реНрд╡ рдШрдЯрдирд╛рдВрдЪреЗ рдкреНрд░рд╕рд╛рд░рдг рд╕реЗрдЯ рдХреЗрд▓реЗ рдЖрд╣реЗ.

URL тАФ рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд░рд╛ рд╕рд░реНрд╡реНрд╣рд░ рдкрддреНрддрд╛.

рдлрд┐рд▓реНрдЯрд░ рдЙрдкрд╕рд░реНрдЧ/рдкреНрд░рддреНрдпрдп рд╣реЗ рдПрдХ рдлрд┐рд▓реНрдЯрд░ рдЖрд╣реЗ рдЬреЗ рддреБрдореНрд╣рд╛рд▓рд╛ рдлрдХреНрдд рдЬреНрдпрд╛ рд╡рд╕реНрддреВрдВрдЪреА рдирд╛рд╡реЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдирд┐рдпрдорд╛рдВрд╢реА рдЬреБрд│рддрд╛рдд рддреНрдпрд╛рдВрдЪреНрдпрд╛рд╕рд╛рдареА рд╡реЗрдмрд╣реБрдХ рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рджреЗрддреЗ. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рд╡реЗрдмрд╣реБрдХ рдХреЗрд╡рд│ .png рд╡рд┐рд╕реНрддрд╛рд░рд╛рд╕рд╣ рдлрд╛рдпрд▓реА рдЯреНрд░рд┐рдЧрд░ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдордзреНрдпреЗ рдлрд┐рд▓реНрдЯрд░ рдкреНрд░рддреНрдпрдп рддреБрдореНрд╣рд╛рд▓рд╛ "png" рд▓рд┐рд╣рд╛рд╡реЗ рд▓рд╛рдЧреЗрд▓.

рд╕рдзреНрдпрд╛, рд╡реЗрдмрд╣реБрдХ рд░рд┐рд╕реАрд╡реНрд╣рд┐рдВрдЧ рд╕рд░реНрд╡реНрд╣рд░рдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдлрдХреНрдд 80 рдЖрдгрд┐ 443 рдкреЛрд░реНрдЯ рд╕рдорд░реНрдерд┐рдд рдЖрд╣реЗрдд.

рдЪрд▓рд╛ рдХреНрд▓рд┐рдХ рдХрд░реВрдпрд╛ рд╣реБрдХ рдЬреЛрдбрд╛ рдЖрдгрд┐ рдЖрдкрдг рдкреБрдвреАрд▓ рдЧреЛрд╖реНрдЯреА рдкрд╛рд╣реВ:

Mail.ru рдХреНрд▓рд╛рдЙрдб рд╕реЛрд▓реНрдпреВрд╢рдиреНрд╕рдЪреНрдпрд╛ S3 рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реНрдЯреЛрд░реЗрдЬрдордзреАрд▓ рд╡реЗрдмрд╣реБрдХрд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдЗрд╡реНрд╣реЗрдВрдЯ-рдЪрд╛рд▓рд┐рдд рдЕрдиреБрдкреНрд░рдпреЛрдЧрд╛рдЪреЗ рдЙрджрд╛рд╣рд░рдг
рд╣реБрдХ рдЬреЛрдбрд▓реЗ.

рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд░рд╛ рд╕рд░реНрд╡реНрд╣рд░ рддреНрдпрд╛рдЪреНрдпрд╛ рд▓реЙрдЧрдордзреНрдпреЗ рд╣реБрдХ рдиреЛрдВрджрдгреА рдкреНрд░рдХреНрд░рд┐рдпреЗрдЪреА рдкреНрд░рдЧрддреА рджрд░реНрд╢рд╡рддреЛ:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80
2020/06/15 12:01:14 [POST] incoming HTTP request from 
95.163.216.92:42530
2020/06/15 12:01:14 Got timestamp: 2020-06-15T15:01:13+03:00 TopicArn: 
mcs5259999770|myfiles-ash|s3:ObjectCreated:*,s3:ObjectRemoved:* Token: 
E2itMqAMUVVZc51pUhFWSp13DoxezvRxkUh5P7LEuk1dEe9y URL: 
http://89.208.199.220/webhook
2020/06/15 12:01:14 Generate responce signature: 
3754ce36636f80dfd606c5254d64ecb2fd8d555c27962b70b4f759f32c76b66d

рдиреЛрдВрджрдгреА рдкреВрд░реНрдг рдЭрд╛рд▓реА рдЖрд╣реЗ. рдкреБрдвреАрд▓ рд╡рд┐рднрд╛рдЧрд╛рдд, рдЖрдореНрд╣реА рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд░реНтАНрдпрд╛ рд╕рд░реНрд╡реНрд╣рд░рдЪреНрдпрд╛ рдСрдкрд░реЗрд╢рдирдЪреНрдпрд╛ рдЕрд▓реНрдЧреЛрд░рд┐рджрдордХрдбреЗ рдЬрд╡рд│реВрди рдкрд╛рд╣реВ.

рд╡реЗрдмрд╣реБрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд▒реНрдпрд╛ рд╕рд░реНрд╡реНрд╣рд░рдЪреЗ рд╡рд░реНрдгрди

рдЖрдордЪреНрдпрд╛ рдЙрджрд╛рд╣рд░рдгрд╛рдд, рд╕рд░реНрд╡реНрд╣рд░ Go рдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓рд╛ рдЖрд╣реЗ. рдЪрд▓рд╛ рддреНрдпрд╛рдЪреНрдпрд╛ рдСрдкрд░реЗрд╢рдирдЪреА рдореВрд▓рднреВрдд рддрддреНрддреНрд╡реЗ рдкрд╛рд╣реВ.

package main

// Generate hmac_sha256_hex
func HmacSha256hex(message string, secret string) string {
}

// Generate hmac_sha256
func HmacSha256(message string, secret string) string {
}

// Send subscription confirmation
func SubscriptionConfirmation(w http.ResponseWriter, req *http.Request, body []byte) {
}

// Send subscription confirmation
func GotRecords(w http.ResponseWriter, req *http.Request, body []byte) {
}

// Liveness probe
func Ping(w http.ResponseWriter, req *http.Request) {
    // log request
    log.Printf("[%s] incoming HTTP Ping request from %sn", req.Method, req.RemoteAddr)
    fmt.Fprintf(w, "Pongn")
}

//Webhook
func Webhook(w http.ResponseWriter, req *http.Request) {
}

func main() {

    // get command line args
    bindPort := flag.Int("port", 80, "number between 1-65535")
    bindAddr := flag.String("address", "", "ip address in dot format")
    flag.StringVar(&actionScript, "script", "", "external script to execute")
    flag.Parse()

    http.HandleFunc("/ping", Ping)
    http.HandleFunc("/webhook", Webhook)

log.Fatal(http.ListenAndServe(*bindAddr+":"+strconv.Itoa(*bindPort), nil))
}

рдореБрдЦреНрдп рдХрд╛рд░реНрдпреЗ рд╡рд┐рдЪрд╛рд░рд╛рдд рдШреНрдпрд╛:

  • Ping() - URL/ping рджреНрд╡рд╛рд░реЗ рдкреНрд░рддрд┐рд╕рд╛рдж рджреЗрдгрд╛рд░рд╛ рдорд╛рд░реНрдЧ, рд▓рд╛рдЗрд╡реНрд╣рдиреЗрд╕ рдкреНрд░реЛрдмрдЪреА рд╕рд░реНрд╡рд╛рдд рд╕реЛрдкреА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА.
  • Webhook() - рдореБрдЦреНрдп рдорд╛рд░реНрдЧ, URL/webhook рд╣рдБрдбрд▓рд░:
    • рдкреНрд░рдХрд╛рд╢рди рд╕реЗрд╡реЗрд╡рд░ рдиреЛрдВрджрдгреАрдЪреА рдкреБрд╖реНрдЯреА рдХрд░рддреЗ (рд╕рджрд╕реНрдпрддрд╛ рдкреБрд╖реНрдЯреАрдХрд░рдг рдХрд╛рд░реНрдпрд╛рд╡рд░ рдЬрд╛),
    • рдЗрдирдХрдорд┐рдВрдЧ рд╡реЗрдмрд╣реБрдХрд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЗ (рдЧреЛрд░реЗрдХреЙрд░реНрдбреНрд╕ рдлрдВрдХреНрд╢рди).
  • рдлрдВрдХреНрд╢рдиреНрд╕ HmacSha256 рдЖрдгрд┐ HmacSha256hex рд╣реА HMAC-SHA256 рдЖрдгрд┐ HMAC-SHA256 рдПрдирдХреНрд░рд┐рдкреНрд╢рди рдЕрд▓реНрдЧреЛрд░рд┐рджрдордЪреА рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдЖрд╣реЗрдд рдЬреНрдпрд╛рдд рд╕реНрд╡рд╛рдХреНрд╖рд░реАрдЪреА рдЧрдгрдирд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╣реЗрдХреНрд╕рд╛рдбреЗрд╕рд┐рдорд▓ рд╕рдВрдЦреНрдпрд╛рдВрдЪреА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореНрд╣рдгреВрди рдЖрдЙрдЯрдкреБрдЯ рдЖрд╣реЗ.
  • main рд╣реЗ рдореБрдЦреНрдп рдХрд╛рд░реНрдп рдЖрд╣реЗ, рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдкреЕрд░рд╛рдореАрдЯрд░реНрд╕рд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЗ рдЖрдгрд┐ URL рд╣рдБрдбрд▓рд░реНрд╕рдЪреА рдиреЛрдВрджрдгреА рдХрд░рддреЗ.

рд╕рд░реНрд╡реНрд╣рд░рджреНрд╡рд╛рд░реЗ рд╕реНрд╡реАрдХрд╛рд░рд▓реЗрд▓реЗ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдкреЕрд░рд╛рдореАрдЯрд░реНрд╕:

  • -рдкреЛрд░реНрдЯ рд╣реЗ рдкреЛрд░реНрдЯ рдЖрд╣реЗ рдЬреНрдпрд╛рд╡рд░ рд╕рд░реНрд╡реНрд╣рд░ рдРрдХреЗрд▓.
  • -address - рд╕рд░реНрд╡реНрд╣рд░ рдРрдХреЗрд▓ рдЕрд╕рд╛ IP рдкрддреНрддрд╛.
  • -рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣рд╛ рдПрдХ рдмрд╛рд╣реНрдп рдкреНрд░реЛрдЧреНрд░рд╛рдо рдЖрд╣реЗ рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рдЗрдирдХрдорд┐рдВрдЧ рд╣реБрдХрд╕рд╛рдареА рдХреЙрд▓ рдХреЗрд▓рд╛ рдЬрд╛рддреЛ.

рдЪрд▓рд╛ рдХрд╛рд╣реА рдХрд╛рд░реНрдпреЗ рдЬрд╡рд│реВрди рдкрд╛рд╣реВ:

//Webhook
func Webhook(w http.ResponseWriter, req *http.Request) {

    // Read body
    body, err := ioutil.ReadAll(req.Body)
    defer req.Body.Close()
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }

    // log request
    log.Printf("[%s] incoming HTTP request from %sn", req.Method, req.RemoteAddr)
    // check if we got subscription confirmation request
    if strings.Contains(string(body), 
""Type":"SubscriptionConfirmation"") {
        SubscriptionConfirmation(w, req, body)
    } else {
        GotRecords(w, req, body)
    }

}

рд╣реЗ рдлрдВрдХреНрд╢рди рдиреЛрдВрджрдгреАрдЪреА рдкреБрд╖реНрдЯреА рдХрд░рдгреНрдпрд╛рдЪреА рд╡рд┐рдирдВрддреА рдХрд┐рдВрд╡рд╛ рд╡реЗрдмрд╣реБрдХ рдЖрд▓реЗ рдЖрд╣реЗ рдХреА рдирд╛рд╣реА рд╣реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ. рдкрд╛рд╕реВрди рдЦрд╛рд▓реАрд▓рдкреНрд░рдорд╛рдгреЗ рджрд╕реНрддрдРрд╡рдЬреАрдХрд░рдг, рдиреЛрдВрджрдгреАрдЪреА рдкреБрд╖реНрдЯреА рдЭрд╛рд▓реНрдпрд╛рд╕, рдкреЛрд╕реНрдЯ рд╡рд┐рдирдВрддреАрдордзреНрдпреЗ рдЦрд╛рд▓реАрд▓ Json рд░рдЪрдирд╛ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдИрд▓:

POST http://test.com HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation
content-type: application/json

{
    "Timestamp":"2019-12-26T19:29:12+03:00",
    "Type":"SubscriptionConfirmation",
    "Message":"You have chosen to subscribe to the topic $topic. To confirm the subscription you need to response with calculated signature",
    "TopicArn":"mcs2883541269|bucketA|s3:ObjectCreated:Put",
    "SignatureVersion":1,
    "Token":┬лRPE5UuG94rGgBH6kHXN9FUPugFxj1hs2aUQc99btJp3E49tA┬╗
}

рдпрд╛ рдкреНрд░рд╢реНрдирд╛рдЪреЗ рдЙрддреНрддрд░ рджреЗрдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ:

content-type: application/json

{"signature":┬лea3fce4bb15c6de4fec365d36bcebbc34ccddf54616d5ca12e1972f82b6d37af┬╗}

рдЬреЗрдереЗ рд╕реНрд╡рд╛рдХреНрд╖рд░реАрдЪреА рдЧрдгрдирд╛ рдХреЗрд▓реА рдЬрд╛рддреЗ:

signature = hmac_sha256(url, hmac_sha256(TopicArn, 
hmac_sha256(Timestamp, Token)))

рд╡реЗрдмрд╣реБрдХ рдЖрд▓реНрдпрд╛рд╕, рдкреЛрд╕реНрдЯ рд╡рд┐рдирдВрддреАрдЪреА рд░рдЪрдирд╛ рдЕрд╢реА рджрд┐рд╕рддреЗ:

POST <url> HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation

{ "Records":
    [
        {
            "s3": {
                "object": {
                    "eTag":"aed563ecafb4bcc5654c597a421547b2",
                    "sequencer":1577453615,
                    "key":"some-file-to-bucket",
                    "size":100
                },
            "configurationId":"1",
            "bucket": {
                "name": "bucketA",
                "ownerIdentity": {
                    "principalId":"mcs2883541269"}
                },
                "s3SchemaVersion":"1.0"
            },
            "eventVersion":"1.0",
            "requestParameters":{
                "sourceIPAddress":"185.6.245.156"
            },
            "userIdentity": {
                "principalId":"2407013e-cbc1-415f-9102-16fb9bd6946b"
            },
            "eventName":"s3:ObjectCreated:Put",
            "awsRegion":"ru-msk",
            "eventSource":"aws:s3",
            "responseElements": {
                "x-amz-request-id":"VGJR5rtJ"
            }
        }
    ]
}

рддреНрдпрд╛рдиреБрд╕рд╛рд░, рд╡рд┐рдирдВрддреАрдиреБрд╕рд╛рд░, рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдбреЗрдЯрд╛рд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╢реА рдХрд░рд╛рд╡реА рд╣реЗ рд╕рдордЬреВрди рдШреЗрдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рдореА рд╕реВрдЪрдХ рдореНрд╣рдгреВрди рдкреНрд░рд╡реЗрд╢ рдирд┐рд╡рдбрд▓рд╛ "Type":"SubscriptionConfirmation", рдХрд╛рд░рдг рддреЗ рд╕рджрд╕реНрдпрддреНрд╡ рдкреБрд╖реНрдЯреАрдХрд░рдг рд╡рд┐рдирдВрддреАрдордзреНрдпреЗ рдЙрдкрд╕реНрдерд┐рдд рдЖрд╣реЗ рдЖрдгрд┐ рд╡реЗрдмрд╣реБрдХрдордзреНрдпреЗ рдЙрдкрд╕реНрдерд┐рдд рдирд╛рд╣реА. POST рд╡рд┐рдирдВрддреАрдордзреНрдпреЗ рдпрд╛ рдПрдВрдЯреНрд░реАрдЪреА рдЙрдкрд╕реНрдерд┐рддреА/рдЕрдиреБрдкрд╕реНрдерд┐рддреА рдпрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд, рдкреНрд░реЛрдЧреНрд░рд╛рдордЪреА рдкреБрдвреАрд▓ рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдПрдХрддрд░ рдлрдВрдХреНрд╢рдирд╡рд░ рдЬрд╛рддреЗ SubscriptionConfirmation, рдХрд┐рдВрд╡рд╛ рдлрдВрдХреНрд╢рдирдордзреНрдпреЗ GotRecords.

рдЖрдореНрд╣реА рд╕рдмрд╕реНрдХреНрд░рд┐рдкреНрд╢рди рдХрдиреНрдлрд░реНрдореЗрд╢рди рдлрдВрдХреНрд╢рдирдЪрд╛ рддрдкрд╢реАрд▓рд╡рд╛рд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдгрд╛рд░ рдирд╛рд╣реА; рддреЗ рдордзреНрдпреЗ рдирдореВрдж рдХреЗрд▓реЗрд▓реНрдпрд╛ рддрддреНрддреНрд╡рд╛рдВрдиреБрд╕рд╛рд░ рд▓рд╛рдЧреВ рдХреЗрд▓реЗ рдЖрд╣реЗ рджрд╕реНрддрдРрд╡рдЬреАрдХрд░рдг. рддреБрдореНрд╣реА рдпрд╛ рдлрдВрдХреНрд╢рдирдЪрд╛ рд╕реЛрд░реНрд╕ рдХреЛрдб рдпреЗрдереЗ рдкрд╛рд╣реВ рд╢рдХрддрд╛ рдкреНрд░рдХрд▓реНрдк git рднрд╛рдВрдбрд╛рд░.

GotRecords рдлрдВрдХреНрд╢рди рдЗрдирдХрдорд┐рдВрдЧ рд╡рд┐рдирдВрддреАрдЪреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддреЗ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рд░реЗрдХреЙрд░реНрдб рдСрдмреНрдЬреЗрдХреНрдЯрд╕рд╛рдареА рдкреЕрд░рд╛рдореАрдЯрд░реНрд╕рд╕рд╣ рдмрд╛рд╣реНрдп рд╕реНрдХреНрд░рд┐рдкреНрдЯ (рдЬреНрдпрд╛рдВрдЪреЗ рдирд╛рд╡ -script рдкреЕрд░рд╛рдореАрдЯрд░рдордзреНрдпреЗ рдкрд╛рд╕ рдХреЗрд▓реЗ рд╣реЛрддреЗ) рдХреЙрд▓ рдХрд░рддреЗ:

  • рдмрд╛рджрд▓реАрдЪреЗ рдирд╛рд╡
  • рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА
  • рдХреНрд░рд┐рдпрд╛:
    • рдХреЙрдкреА - рдореВрд│ рд╡рд┐рдирдВрддреАрдордзреНрдпреЗ рдЕрд╕рд▓реНрдпрд╛рд╕ EventName = ObjectCreated | рдкреБрдЯрдСрдмреНрдЬреЗрдХреНрдЯ | рдкреБрдЯрдСрдмреНрдЬреЗрдХреНрдЯрдХреЙрдкреА
    • рд╣рдЯрд╡рд╛ - рдЬрд░ рдореВрд│ рд╡рд┐рдирдВрддреАрдордзреНрдпреЗ рдЕрд╕реЗрд▓ EventName = ObjectRemoved | рдСрдмреНрдЬреЗрдХреНрдЯ рд╣рдЯрд╡рд╛

рдЕрд╢рд╛ рдкреНрд░рдХрд╛рд░реЗ, рд╡рд░реНрдгрди рдХреЗрд▓реНрдпрд╛рдкреНрд░рдорд╛рдгреЗ, рдкреЛрд╕реНрдЯ рд╡рд┐рдирдВрддреАрд╕рд╣ рд╣реБрдХ рдЖрд▓реНрдпрд╛рд╕ рдЙрдЪреНрдЪ, рдЖрдгрд┐ рдкреЕрд░рд╛рдореАрдЯрд░ -script=script.sh рдирдВрддрд░ рд╕реНрдХреНрд░рд┐рдкреНрдЯрд▓рд╛ рдЦрд╛рд▓реАрд▓рдкреНрд░рдорд╛рдгреЗ рдХреЙрд▓ рдХреЗрд▓реЗ рдЬрд╛рдИрд▓:

script.sh  bucketA some-file-to-bucket copy

рд╣реЗ рд╕рдордЬрд▓реЗ рдкрд╛рд╣рд┐рдЬреЗ рдХреА рд╣реЗ рд╡реЗрдмрд╣реВрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдгрд╛рд░реЗ рд╕рд░реНрд╡реНрд╣рд░ рд╣реЗ рд╕рдВрдкреВрд░реНрдг рдЙрддреНрдкрд╛рджрди рд╕рдорд╛рдзрд╛рди рдирд╛рд╣реА, рдкрд░рдВрддреБ рд╕рдВрднрд╛рд╡реНрдп рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреАрдЪреЗ рдПрдХ рд╕рд░рд▓реАрдХреГрдд рдЙрджрд╛рд╣рд░рдг рдЖрд╣реЗ.

рдХрд╛рдорд╛рдЪреЗ рдЙрджрд╛рд╣рд░рдг

MCS рдордзреАрд▓ рдореБрдЦреНрдп рдмрдХреЗрдЯрдкрд╛рд╕реВрди AWS рдордзреАрд▓ рдмреЕрдХрдЕрдк рдмрдХреЗрдЯрдордзреНрдпреЗ рдлрд╛рдЗрд▓реНрд╕ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЭ рдХрд░реВ. рдореБрдЦреНрдп рдмрд╛рджрд▓реАрд▓рд╛ myfiles-ash рдореНрд╣рдгрддрд╛рдд, рдмреЕрдХрдЕрдкрд▓рд╛ myfiles-backup рдореНрд╣рдгрддрд╛рдд (AWS рдордзреНрдпреЗ рдмрдХреЗрдЯ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдпрд╛ рд▓реЗрдЦрд╛рдЪреНрдпрд╛ рд╡реНрдпрд╛рдкреНрддреАрдЪреНрдпрд╛ рдмрд╛рд╣реЗрд░ рдЖрд╣реЗ). рддреНрдпрд╛рдиреБрд╕рд╛рд░, рдЬреЗрд╡реНрд╣рд╛ рдПрдЦрд╛рджреА рдлрд╛рдИрд▓ рдореБрдЦреНрдп рдмрдХреЗрдЯрдордзреНрдпреЗ рдареЗрд╡рд▓реА рдЬрд╛рддреЗ, рддреЗрд╡реНрд╣рд╛ рддрд┐рдЪреА рдкреНрд░рдд рдмреЕрдХрдЕрдкрдордзреНрдпреЗ рджрд┐рд╕рд▓реА рдкрд╛рд╣рд┐рдЬреЗ рдЖрдгрд┐ рдЬреЗрд╡реНрд╣рд╛ рддреА рдореБрдЦреНрдпрдордзреВрди рд╣рдЯрд╡рд┐рд▓реА рдЬрд╛рддреЗ рддреЗрд╡реНрд╣рд╛ рддреА рдмреЕрдХрдЕрдкрдордзреНрдпреЗ рд╣рдЯрд╡рд┐рд▓реА рдЬрд╛рд╡реА.

рдЖрдореНрд╣реА awscli рдпреБрдЯрд┐рд▓рд┐рдЯреА рд╡рд╛рдкрд░реВрди рдмрдХреЗрдЯрд╕рд╣ рдХрд╛рдо рдХрд░реВ, рдЬреЗ MCS рдХреНрд▓рд╛рдЙрдб рд╕реНрдЯреЛрд░реЗрдЬ рдЖрдгрд┐ AWS рдХреНрд▓рд╛рдЙрдб рд╕реНрдЯреЛрд░реЗрдЬ рдпрд╛ рджреЛрдиреНрд╣реАрд╢реА рд╕реБрд╕рдВрдЧрдд рдЖрд╣реЗ.

ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install awscli
Reading package lists... Done
Building dependency tree
Reading state information... Done
After this operation, 34.4 MB of additional disk space will be used.
Unpacking awscli (1.14.44-1ubuntu1) ...
Setting up awscli (1.14.44-1ubuntu1) ...

S3 MCS API рдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░реВрдпрд╛:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile mcs
AWS Access Key ID [None]: hdywEPtuuJTExxxxxxxxxxxxxx
AWS Secret Access Key [None]: hDz3SgxKwXoxxxxxxxxxxxxxxxxxx
Default region name [None]:
Default output format [None]:

AWS S3 API рдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░реВрдпрд╛:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile aws
AWS Access Key ID [None]: AKIAJXXXXXXXXXXXX
AWS Secret Access Key [None]: dfuerphOLQwu0CreP5Z8l5fuXXXXXXXXXXXXXXXX
Default region name [None]:
Default output format [None]:

рдЪрд▓рд╛ рдкреНрд░рд╡реЗрд╢ рддрдкрд╛рд╕реВ:

AWS рд▓рд╛:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile aws
2020-07-06 08:44:11 myfiles-backup

MCS рд╕рд╛рдареА, рдХрдорд╛рдВрдб рдЪрд╛рд▓рд╡рддрд╛рдирд╛ рддреБрдореНрд╣рд╛рд▓рд╛ тАФendpoint-url рдЬреЛрдбрдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile mcs --endpoint-url 
https://hb.bizmrg.com
2020-02-04 06:38:05 databasebackups-0cdaaa6402d4424e9676c75a720afa85
2020-05-27 10:08:33 myfiles-ash

рдкреНрд░рд╡реЗрд╢ рдХреЗрд▓рд╛.

рдЖрддрд╛ рдЗрдирдХрдорд┐рдВрдЧ рд╣реБрдХрд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓рд┐рд╣реВ рдпрд╛, рддреНрдпрд╛рд▓рд╛ s3_backup_mcs_aws.sh рдореНрд╣рдгреВ.

#!/bin/bash
# Require aws cli
# if file added тАФ copy it to backup bucket
# if file removed тАФ remove it from backup bucket
# Variables
ENDPOINT_MCS="https://hb.bizmrg.com"
AWSCLI_MCS=`which aws`" --endpoint-url ${ENDPOINT_MCS} --profile mcs s3"
AWSCLI_AWS=`which aws`" --profile aws s3"
BACKUP_BUCKET="myfiles-backup"

SOURCE_BUCKET=""
SOURCE_FILE=""
ACTION=""

SOURCE="s3://${SOURCE_BUCKET}/${SOURCE_FILE}"
TARGET="s3://${BACKUP_BUCKET}/${SOURCE_FILE}"
TEMP="/tmp/${SOURCE_BUCKET}/${SOURCE_FILE}"

case ${ACTION} in
    "copy")
    ${AWSCLI_MCS} cp "${SOURCE}" "${TEMP}"
    ${AWSCLI_AWS} cp "${TEMP}" "${TARGET}"
    rm ${TEMP}
    ;;

    "delete")
    ${AWSCLI_AWS} rm ${TARGET}
    ;;

    *)
    echo "Usage: 
#!/bin/bash
# Require aws cli
# if file added тАФ copy it to backup bucket
# if file removed тАФ remove it from backup bucket
# Variables
ENDPOINT_MCS="https://hb.bizmrg.com"
AWSCLI_MCS=`which aws`" --endpoint-url ${ENDPOINT_MCS} --profile mcs s3"
AWSCLI_AWS=`which aws`" --profile aws s3"
BACKUP_BUCKET="myfiles-backup"
SOURCE_BUCKET="${1}"
SOURCE_FILE="${2}"
ACTION="${3}"
SOURCE="s3://${SOURCE_BUCKET}/${SOURCE_FILE}"
TARGET="s3://${BACKUP_BUCKET}/${SOURCE_FILE}"
TEMP="/tmp/${SOURCE_BUCKET}/${SOURCE_FILE}"
case ${ACTION} in
"copy")
${AWSCLI_MCS} cp "${SOURCE}" "${TEMP}"
${AWSCLI_AWS} cp "${TEMP}" "${TARGET}"
rm ${TEMP}
;;
"delete")
${AWSCLI_AWS} rm ${TARGET}
;;
*)
echo "Usage: ${0} sourcebucket sourcefile copy/delete"
exit 1
;;
esac
sourcebucket sourcefile copy/delete" exit 1 ;; esac

рдЪрд▓рд╛ рд╕рд░реНрд╡реНрд╣рд░ рд╕реБрд░реВ рдХрд░реВрдпрд╛:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80 -
script scripts/s3_backup_mcs_aws.sh

рддреЗ рдХрд╕реЗ рдХрд╛рд░реНрдп рдХрд░рддреЗ рддреЗ рдкрд╛рд╣реВрдпрд╛. рдЪреНрдпрд╛ рдорд╛рдзреНрдпрдорд╛рддреВрди MCS рд╡реЗрдм рдЗрдВрдЯрд░рдлреЗрд╕ test.txt рдлрд╛рдЗрд▓ myfiles-ash рдмрдХреЗрдЯрдордзреНрдпреЗ рдЬреЛрдбрд╛. рдХрдиреНрд╕реЛрд▓ рд▓реЙрдЧ рджрд╛рдЦрд╡рддрд╛рдд рдХреА рд╡реЗрдмрд╣реБрдХ рд╕рд░реНрд╡реНрд╣рд░рд▓рд╛ рд╡рд┐рдирдВрддреА рдХреЗрд▓реА рдЧреЗрд▓реА рд╣реЛрддреА:

2020/07/06 09:43:08 [POST] incoming HTTP request from 
95.163.216.92:56612
download: s3://myfiles-ash/test.txt to ../../../tmp/myfiles-ash/test.txt
upload: ../../../tmp/myfiles-ash/test.txt to 
s3://myfiles-backup/test.txt

AWS рдордзреАрд▓ myfiles-рдмреЕрдХрдЕрдк рдмрдХреЗрдЯрдЪреА рд╕рд╛рдордЧреНрд░реА рддрдкрд╛рд╕реВрдпрд╛:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls 
myfiles-backup
2020-07-06 09:43:10       1104 test.txt

рдЖрддрд╛, рд╡реЗрдм рдЗрдВрдЯрд░рдлреЗрд╕рджреНрд╡рд╛рд░реЗ, рдЖрдкрдг myfiles-ash рдмрдХреЗрдЯрдордзреВрди рдлрд╛рдЗрд▓ рд╣рдЯрд╡реВ.

рд╕рд░реНрд╡реНрд╣рд░ рд▓реЙрдЧ:

2020/07/06 09:44:46 [POST] incoming HTTP request from 
95.163.216.92:58224
delete: s3://myfiles-backup/test.txt

рдмрд╛рджрд▓реА рд╕рд╛рдордЧреНрд░реА:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls 
myfiles-backup
ubuntu@ubuntu-basic-1-2-10gb:~$

рдлрд╛рдЗрд▓ рд╣рдЯрд╡рд┐рд▓реА рдЧреЗрд▓реА рдЖрд╣реЗ, рд╕рдорд╕реНрдпрд╛ рд╕реЛрдбрд╡рд▓реА рдЖрд╣реЗ.

рдирд┐рд╖реНрдХрд░реНрд╖ рдЖрдгрд┐ ToDo

рдпрд╛ рд▓реЗрдЦрд╛рдд рд╡рд╛рдкрд░рд▓реЗрд▓реЗ рд╕рд░реНрд╡ рдХреЛрдб рдЖрд╣реЗ рдорд╛рдЭреНрдпрд╛ рднрд╛рдВрдбрд╛рд░рд╛рдд. рд╡реЗрдмрд╣реБрдХрдЪреА рдиреЛрдВрджрдгреА рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╕реНрдХреНрд░рд┐рдкреНрдЯрдЪреА рдЙрджрд╛рд╣рд░рдгреЗ рдЖрдгрд┐ рд╕реНрд╡рд╛рдХреНрд╖рд░реА рдореЛрдЬрдгреНрдпрд╛рдЪреА рдЙрджрд╛рд╣рд░рдгреЗ рджреЗрдЦреАрд▓ рдЖрд╣реЗрдд.

рд╣рд╛ рдХреЛрдб рддреБрдореНрд╣реА рддреБрдордЪреНрдпрд╛ рдЕреЕрдХреНрдЯрд┐рд╡реНрд╣рд┐рдЯреАрдордзреНрдпреЗ S3 рд╡реЗрдмрд╣реБрдХ рдХрд╕реЗ рд╡рд╛рдкрд░реВ рд╢рдХрддрд╛ рдпрд╛рдЪреНрдпрд╛ рдЙрджрд╛рд╣рд░рдгрд╛рд╢рд┐рд╡рд╛рдп рджреБрд╕рд░реЗ рдХрд╛рд╣реАрд╣реА рдирд╛рд╣реА. рдореА рд╕реБрд░реБрд╡рд╛рддреАрд▓рд╛ рдореНрд╣рдЯрд▓реНрдпрд╛рдкреНрд░рдорд╛рдгреЗ, рдЬрд░ рддреБрдореНрд╣реА рдЕрд╕рд╛ рд╕рд░реНрд╡реНрд╣рд░ рдЙрддреНрдкрд╛рджрдирд╛рдд рд╡рд╛рдкрд░рдгреНрдпрд╛рдЪреА рдпреЛрдЬрдирд╛ рдЖрдЦрдд рдЕрд╕рд╛рд▓, рддрд░ рддреБрдореНрд╣рд╛рд▓рд╛ рдЕрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХрд╛рдорд╛рд╕рд╛рдареА рд╕рд░реНрд╡реНрд╣рд░ рдкреБрдиреНрд╣рд╛ рд▓рд┐рд╣рд╛рд╡рд╛ рд▓рд╛рдЧреЗрд▓: рдпреЗрдгрд╛рд░реНтАНрдпрд╛ рд╡реЗрдмрд╣реБрдХрдЪреА рдПрдХрд╛ рд░рд╛рдВрдЧреЗрдд рдиреЛрдВрджрдгреА рдХрд░рд╛ (RabbitMQ рдХрд┐рдВрд╡рд╛ NATS), рдЖрдгрд┐ рддреЗрдереВрди рддреНрдпрд╛рдВрдЪреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рд╛ рдЖрдгрд┐ рддреНрдпрд╛рд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рд╛. рдХрд╛рдордЧрд╛рд░ рдЕрд░реНрдЬрд╛рдВрд╕рд╣. рдЕрдиреНрдпрдерд╛, рдЬреЗрд╡реНрд╣рд╛ рд╡реЗрдмрд╣реБрдХ рдореЛрдареНрдпрд╛ рдкреНрд░рдорд╛рдгрд╛рд╡рд░ рдпреЗрддрд╛рдд, рддреЗрд╡реНрд╣рд╛ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рд░реНрдпреЗ рдкреВрд░реНрдг рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╕рд░реНрд╡реНрд╣рд░ рд╕рдВрд╕рд╛рдзрдирд╛рдВрдЪреА рдХрдорддрд░рддрд╛ рднрд╛рд╕реВ рд╢рдХрддреЗ. рд░рд╛рдВрдЧрд╛рдВрдЪреА рдЙрдкрд╕реНрдерд┐рддреА рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рд╕рд░реНрд╡реНрд╣рд░ рдЖрдгрд┐ рдХрд╛рдордЧрд╛рд░рд╛рдВрдЪреЗ рд╡рд┐рддрд░рдг рдХрд░рдгреНрдпрд╛рд╕ рддрд╕реЗрдЪ рдЕрдпрд╢рд╕реНрд╡реА рдЭрд╛рд▓реНрдпрд╛рд╕ рдкреБрдирд░рд╛рд╡реГрддреНрддреА рдХрд╛рд░реНрдпрд╛рдВрд╕рд╣ рд╕рдорд╕реНрдпрд╛ рд╕реЛрдбрд╡рд┐рдгреНрдпрд╛рд╕ рдЕрдиреБрдорддреА рджреЗрддреЗ. рд▓реЙрдЧрд┐рдВрдЧрд▓рд╛ рдЕрдзрд┐рдХ рддрдкрд╢реАрд▓рд╡рд╛рд░ рдЖрдгрд┐ рдЕрдзрд┐рдХ рдкреНрд░рдорд╛рдгрд┐рдд рдордзреНрдпреЗ рдмрджрд▓рдгреЗ рджреЗрдЦреАрд▓ рдЙрдЪрд┐рдд рдЖрд╣реЗ.

рд░рд┐рдЭрд░реНрд╡реНрд╣рд░реНрд╡реНрд╣рд░ ... рдкреБрдиреНрд╣рд╛!

рд╡рд┐рд╖рдпрд╛рд╡рд░ рдЕрдзрд┐рдХ рд╡рд╛рдЪрди:

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛